From 8c6d300162e0a1b7f072f81af80027e5aec36d14 Mon Sep 17 00:00:00 2001 From: bigboydiamonds <57741810+bigboydiamonds@users.noreply.github.com> Date: Tue, 12 Mar 2024 23:36:50 -0700 Subject: [PATCH 01/29] FE Release 2024-03-12 (#2271) --- packages/synapse-interface/CHANGELOG.md | 27 ++ .../synapse-interface/components/Banner.tsx | 271 ------------------ .../Maintenance/AnnouncementBanner.tsx | 105 +++++++ .../Maintenance/EthDencunUpgrade.tsx | 30 ++ .../Maintenance/EventCountdownProgressBar.tsx | 91 ++++++ .../Maintenance/LinearAnimatedProgressBar.tsx | 111 +++++++ .../BridgeExchangeRateInfo.tsx | 2 +- .../BridgeTransactionButton.tsx | 22 +- packages/synapse-interface/package.json | 2 +- packages/synapse-interface/pages/index.tsx | 4 +- .../pages/state-managed-bridge/index.tsx | 139 +++++---- .../synapse-interface/public/blacklist.json | 5 +- services/rfq/relayer/reldb/db.go | 4 + .../reldb/quoterequeststatus_string.go | 5 +- services/rfq/relayer/service/chainindexer.go | 9 +- 15 files changed, 478 insertions(+), 349 deletions(-) delete mode 100644 packages/synapse-interface/components/Banner.tsx create mode 100644 packages/synapse-interface/components/Maintenance/AnnouncementBanner.tsx create mode 100644 packages/synapse-interface/components/Maintenance/EthDencunUpgrade.tsx create mode 100644 packages/synapse-interface/components/Maintenance/EventCountdownProgressBar.tsx create mode 100644 packages/synapse-interface/components/Maintenance/LinearAnimatedProgressBar.tsx diff --git a/packages/synapse-interface/CHANGELOG.md b/packages/synapse-interface/CHANGELOG.md index 9c47fa5258..96405d22bf 100644 --- a/packages/synapse-interface/CHANGELOG.md +++ b/packages/synapse-interface/CHANGELOG.md @@ -3,6 +3,33 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.7.0](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.6.2...@synapsecns/synapse-interface@0.7.0) (2024-03-13) + + +### Features + +* **synapse-interface:** maintenance notification components + eth dencun pause ([#2260](https://github.com/synapsecns/sanguine/issues/2260)) ([9ffae5b](https://github.com/synapsecns/sanguine/commit/9ffae5b640f904818fdd4b198c069042f05ffb29)) + + + + + +## [0.6.2](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.6.1...@synapsecns/synapse-interface@0.6.2) (2024-03-13) + +**Note:** Version bump only for package @synapsecns/synapse-interface + + + + + +## [0.6.1](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.6.0...@synapsecns/synapse-interface@0.6.1) (2024-03-13) + +**Note:** Version bump only for package @synapsecns/synapse-interface + + + + + # [0.6.0](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.5.1...@synapsecns/synapse-interface@0.6.0) (2024-03-12) diff --git a/packages/synapse-interface/components/Banner.tsx b/packages/synapse-interface/components/Banner.tsx deleted file mode 100644 index 4c9f1e567b..0000000000 --- a/packages/synapse-interface/components/Banner.tsx +++ /dev/null @@ -1,271 +0,0 @@ -import { useEffect, useState } from 'react' - -const BANNER_VERSION = '4' - -export const Banner = () => { - const [hasMounted, setHasMounted] = useState(false) - const [showBanner, setShowBanner] = useState(false) - - useEffect(() => { - setHasMounted(true) - }, []) - - useEffect(() => { - if (hasMounted) { - const storedBannerVersion = localStorage.getItem('bannerVersion') - const storedShowBanner = localStorage.getItem('showBanner') - - setShowBanner( - storedBannerVersion !== BANNER_VERSION || - storedShowBanner === null || - storedShowBanner === 'true' - ) - } - }, [hasMounted]) - - useEffect(() => { - if (hasMounted) { - localStorage.setItem('showBanner', showBanner.toString()) - localStorage.setItem('bannerVersion', BANNER_VERSION) - } - }, [showBanner, hasMounted]) - - if (!showBanner || !hasMounted) return null - - return ( -
- -
- ) -} - -export const CustomBanner = ({ text, link }: { text: string; link?: any }) => { - const [hasMounted, setHasMounted] = useState(false) - const [showBanner, setShowBanner] = useState(false) - - useEffect(() => { - setHasMounted(true) - }, []) - - useEffect(() => { - if (hasMounted) { - const storedBannerVersion = localStorage.getItem('customBannerVersion') - const storedShowBanner = localStorage.getItem('customShowBanner') - - setShowBanner( - storedBannerVersion !== BANNER_VERSION || - storedShowBanner === null || - storedShowBanner === 'true' - ) - } - }, [hasMounted]) - - useEffect(() => { - if (hasMounted) { - localStorage.setItem('customShowBanner', showBanner.toString()) - localStorage.setItem('customBannerVersion', BANNER_VERSION) - } - }, [showBanner, hasMounted]) - - if (!showBanner || !hasMounted) return null - - return ( -
- -
- ) -} - -export const InterruptedServiceBanner = () => { - const [hasMounted, setHasMounted] = useState(false) - const [showBanner, setShowBanner] = useState(false) - - useEffect(() => { - setHasMounted(true) - }, []) - - useEffect(() => { - if (hasMounted) { - const storedBannerVersion = localStorage.getItem('bannerVersion') - const storedShowBanner = localStorage.getItem('showInterruptedBanner') - - setShowBanner( - storedBannerVersion !== BANNER_VERSION || - storedShowBanner === null || - storedShowBanner === 'true' - ) - } - }, [hasMounted]) - - useEffect(() => { - if (hasMounted) { - localStorage.setItem('showInterruptedBanner', showBanner.toString()) - localStorage.setItem('bannerVersion', BANNER_VERSION) - } - }, [showBanner, hasMounted]) - - if (!showBanner || !hasMounted) return null - - return ( -
- -
- ) -} diff --git a/packages/synapse-interface/components/Maintenance/AnnouncementBanner.tsx b/packages/synapse-interface/components/Maintenance/AnnouncementBanner.tsx new file mode 100644 index 0000000000..42dc33dc97 --- /dev/null +++ b/packages/synapse-interface/components/Maintenance/AnnouncementBanner.tsx @@ -0,0 +1,105 @@ +import { useState, useEffect } from 'react' + +/** + * Reusable Annoucement Banner with custom Start/End Time + * @param bannerId: store in $MMDDYYYY-$BANNER_NAME format (e.g 03132024-ETH-DENCUN) + * @param bannerContents: contents to display in banner + * @param startDate: start date to show banner + * @param endDate: end date to remove banner + */ +export const AnnouncementBanner = ({ + bannerId, + bannerContents, + startDate, + endDate, +}: { + bannerId: string + bannerContents: any + startDate: Date + endDate: Date +}) => { + const [hasMounted, setHasMounted] = useState(false) + const [showBanner, setShowBanner] = useState(false) + + const currentDate = new Date() + + const isStarted = + Math.floor(currentDate.getTime()) - Math.floor(startDate.getTime()) >= 0 + const isComplete = + Math.floor(currentDate.getTime()) - Math.floor(endDate.getTime()) >= 0 + + useEffect(() => { + setHasMounted(true) + }, []) + + useEffect(() => { + if (hasMounted && isStarted && !isComplete) { + const storedShowBanner = localStorage.getItem('showAnnoucementBanner') + const storedBannerId = localStorage.getItem('bannerId') + + setShowBanner( + Boolean( + storedBannerId !== bannerId || + storedShowBanner === null || + storedShowBanner === 'true' + ) + ) + } + }, [hasMounted]) + + useEffect(() => { + if (hasMounted && isStarted && !isComplete) { + localStorage.setItem('showAnnoucementBanner', showBanner.toString()) + localStorage.setItem('bannerId', bannerId) + } + }, [showBanner, hasMounted]) + + if (!showBanner || !hasMounted || isComplete) return null + + return ( +
+ +
+ ) +} diff --git a/packages/synapse-interface/components/Maintenance/EthDencunUpgrade.tsx b/packages/synapse-interface/components/Maintenance/EthDencunUpgrade.tsx new file mode 100644 index 0000000000..45c40d6c15 --- /dev/null +++ b/packages/synapse-interface/components/Maintenance/EthDencunUpgrade.tsx @@ -0,0 +1,30 @@ +import { AnnouncementBanner } from './AnnouncementBanner' + +/** + * Start: 15 min prior to Eth Dencun Upgrade Time @ 3/13/24 13:55 UTC + * End: 30 min after start of Eth Decun Upgrade Time + */ +export const ETH_DENCUN_BANNER_START = new Date( + Date.UTC(2024, 2, 13, 13, 20, 0) +) +export const ETH_DENCUN_START_DATE = new Date(Date.UTC(2024, 2, 13, 13, 40, 0)) +export const ETH_DENCUN_END_DATE = new Date(Date.UTC(2024, 2, 13, 14, 30, 0)) + +export const EthDencunUpgradeBanner = () => { + return ( + +
+ Synapse Bridge is upgrading ahead of the Ethereum Dencun upgrade + (March 13, 13:55 UTC, 9:55 EST). +
+
Will be back online shortly ahead of the network upgrade.
+ + } + startDate={ETH_DENCUN_BANNER_START} + endDate={ETH_DENCUN_END_DATE} + /> + ) +} diff --git a/packages/synapse-interface/components/Maintenance/EventCountdownProgressBar.tsx b/packages/synapse-interface/components/Maintenance/EventCountdownProgressBar.tsx new file mode 100644 index 0000000000..b4f60eb5ba --- /dev/null +++ b/packages/synapse-interface/components/Maintenance/EventCountdownProgressBar.tsx @@ -0,0 +1,91 @@ +import { useMemo } from 'react' +import { LinearAnimatedProgressBar } from './LinearAnimatedProgressBar' +import { useIntervalTimer } from '@/utils/hooks/useIntervalTimer' + +export const useEventCountdownProgressBar = ( + eventLabel: string, + startDate: Date, + endDate: Date +): { + isPending: boolean + isComplete: boolean + EventCountdownProgressBar: JSX.Element +} => { + useIntervalTimer(60000) + const currentDate = new Date() + const currentTimeInSeconds = currentDate.getTime() / 1000 + const startTimeInSeconds = Math.floor(startDate.getTime() / 1000) + const endTimeInSeconds = Math.floor(endDate.getTime() / 1000) + + const timeRemainingInSeconds = endTimeInSeconds - currentTimeInSeconds + const timeRemainingInMinutes = Math.ceil(timeRemainingInSeconds / 60) + + const isStarted = currentTimeInSeconds >= startTimeInSeconds + const isComplete = timeRemainingInSeconds <= 0 + const isPending = isStarted && !isComplete + + let status: 'idle' | 'pending' | 'complete' + + if (isComplete) { + status = 'complete' + } else if (isPending) { + status = 'pending' + } else { + status = 'idle' + } + + return { + isPending, + isComplete, + EventCountdownProgressBar: ( + + ), + } +} + +export const EventCountdownProgressBar = ({ + eventLabel, + startTime, + endTime, + status, + timeRemaining, +}: { + eventLabel: string + startTime: number + endTime: number + status: 'idle' | 'pending' | 'complete' + timeRemaining: number +}) => { + if (status === 'pending') { + return ( +
+
+
{eventLabel}
+
{timeRemaining}m remaining
+
+
+ +
+
+ ) + } else { + return null + } +} diff --git a/packages/synapse-interface/components/Maintenance/LinearAnimatedProgressBar.tsx b/packages/synapse-interface/components/Maintenance/LinearAnimatedProgressBar.tsx new file mode 100644 index 0000000000..d2c90fbe7b --- /dev/null +++ b/packages/synapse-interface/components/Maintenance/LinearAnimatedProgressBar.tsx @@ -0,0 +1,111 @@ +import { memo } from 'react' +import { getTimeMinutesBeforeNow } from '@/utils/time' + +/** + * @param id unique identifier for progress bar instance + * @param startTime start time in unix seconds + * @param endTime end time in unix seconds + * @param status progress status + */ +export const LinearAnimatedProgressBar = memo( + ({ + id, + startTime, + endTime, + status, + }: { + id: string + startTime: number + endTime: number + status: 'idle' | 'pending' | 'complete' + }) => { + const currentTime = Math.floor(getTimeMinutesBeforeNow(0)) + const elapsedTimeInSeconds = currentTime - startTime + const remainingTimeInSeconds = endTime - currentTime + const totalTimeInSeconds = endTime - startTime + + const percentElapsed = Math.floor( + (elapsedTimeInSeconds / totalTimeInSeconds) * 100 + ) + + const isComplete = status === 'complete' + + let duration = isComplete ? 0.5 : remainingTimeInSeconds + + const synapsePurple = 'hsl(265deg 100% 75%)' + const tailwindGreen400 = 'rgb(74 222 128)' + const height = 3 + const progressId = `progress-${id}` + const maskId = `mask-${id}` + + return ( + + + + + + + + + + + + + + + + + + {isComplete && ( + + )} + + {isComplete && ( + + )} + + ) + } +) diff --git a/packages/synapse-interface/components/StateManagedBridge/BridgeExchangeRateInfo.tsx b/packages/synapse-interface/components/StateManagedBridge/BridgeExchangeRateInfo.tsx index fcff6c09c2..0824226296 100644 --- a/packages/synapse-interface/components/StateManagedBridge/BridgeExchangeRateInfo.tsx +++ b/packages/synapse-interface/components/StateManagedBridge/BridgeExchangeRateInfo.tsx @@ -24,7 +24,7 @@ const BridgeExchangeRateInfo = () => {
- {/* */} +
diff --git a/packages/synapse-interface/components/StateManagedBridge/BridgeTransactionButton.tsx b/packages/synapse-interface/components/StateManagedBridge/BridgeTransactionButton.tsx index 3e046652f5..c10e98aa6a 100644 --- a/packages/synapse-interface/components/StateManagedBridge/BridgeTransactionButton.tsx +++ b/packages/synapse-interface/components/StateManagedBridge/BridgeTransactionButton.tsx @@ -6,13 +6,8 @@ import { RootState } from '@/store/store' import { useAccount, useNetwork, useSwitchNetwork } from 'wagmi' import { useEffect, useState } from 'react' import { isAddress } from '@ethersproject/address' -import {} from 'wagmi' -import { - useConnectModal, - useAccountModal, - useChainModal, -} from '@rainbow-me/rainbowkit' +import { useConnectModal } from '@rainbow-me/rainbowkit' import { stringToBigInt } from '@/utils/bigint/format' import { useBridgeState } from '@/slices/bridge/hooks' import { usePortfolioBalances } from '@/slices/portfolio/hooks' @@ -22,14 +17,15 @@ export const BridgeTransactionButton = ({ approveTxn, executeBridge, isApproved, + isBridgePaused, }) => { const [isConnected, setIsConnected] = useState(false) const { openConnectModal } = useConnectModal() const { chain } = useNetwork() - const { chains, error, pendingChainId, switchNetwork } = useSwitchNetwork() + const { chains, switchNetwork } = useSwitchNetwork() - const { address, isConnected: isConnectedInit } = useAccount({ + const { isConnected: isConnectedInit } = useAccount({ onDisconnect() { setIsConnected(false) }, @@ -76,7 +72,8 @@ export const BridgeTransactionButton = ({ (showDestinationAddress && !destinationAddress) || (isConnected && !sufficientBalance) || PAUSED_FROM_CHAIN_IDS.includes(fromChainId) || - PAUSED_TO_CHAIN_IDS.includes(toChainId) + PAUSED_TO_CHAIN_IDS.includes(toChainId) || + isBridgePaused let buttonProperties @@ -87,7 +84,12 @@ export const BridgeTransactionButton = ({ return fromTokenDecimals ? stringToBigInt(fromValue, fromTokenDecimals) : 0 }, [fromValue, fromTokenDecimals]) - if (!fromChainId) { + if (isBridgePaused) { + buttonProperties = { + label: 'Bridge paused', + onClick: null, + } + } else if (!fromChainId) { buttonProperties = { label: 'Please select Origin network', onClick: null, diff --git a/packages/synapse-interface/package.json b/packages/synapse-interface/package.json index 1ad300b4e5..249706cdc3 100644 --- a/packages/synapse-interface/package.json +++ b/packages/synapse-interface/package.json @@ -1,6 +1,6 @@ { "name": "@synapsecns/synapse-interface", - "version": "0.6.0", + "version": "0.7.0", "private": true, "engines": { "node": ">=16.0.0" diff --git a/packages/synapse-interface/pages/index.tsx b/packages/synapse-interface/pages/index.tsx index 1b0902078b..ae17084eea 100644 --- a/packages/synapse-interface/pages/index.tsx +++ b/packages/synapse-interface/pages/index.tsx @@ -1,9 +1,9 @@ -import { Banner } from '@/components/Banner' import StateManagedBridge from './state-managed-bridge' import { Portfolio } from '@/components/Portfolio/Portfolio' import { LandingPageWrapper } from '@/components/layouts/LandingPageWrapper' import ReactGA from 'react-ga' import useSyncQueryParamsWithBridgeState from '@/utils/hooks/useSyncQueryParamsWithBridgeState' +import { EthDencunUpgradeBanner } from '@/components/Maintenance/EthDencunUpgrade' // TODO: someone should add this to the .env, disable if blank, etc. // this is being added as a hotfix to assess user load on the synapse explorer api @@ -20,7 +20,7 @@ const Home = () => { data-test-id="bridge-page" className="relative z-0 flex-1 h-full overflow-y-auto focus:outline-none" > - +
diff --git a/packages/synapse-interface/pages/state-managed-bridge/index.tsx b/packages/synapse-interface/pages/state-managed-bridge/index.tsx index 534b00f88f..f23db2701e 100644 --- a/packages/synapse-interface/pages/state-managed-bridge/index.tsx +++ b/packages/synapse-interface/pages/state-managed-bridge/index.tsx @@ -86,6 +86,11 @@ import { } from '@/slices/priceDataSlice' import { isTransactionReceiptError } from '@/utils/isTransactionReceiptError' import { SwitchButton } from '@/components/buttons/SwitchButton' +import { useEventCountdownProgressBar } from '@/components/Maintenance/EventCountdownProgressBar' +import { + ETH_DENCUN_START_DATE, + ETH_DENCUN_END_DATE, +} from '@/components/Maintenance/EthDencunUpgrade' const StateManagedBridge = () => { const { address } = useAccount() @@ -518,6 +523,15 @@ const StateManagedBridge = () => { const springClass = '-mt-4 fixed z-50 w-full h-full bg-opacity-50 bg-[#343036]' + const { + isPending: isUpgradePending, + EventCountdownProgressBar: EthDencunEventCountdownProgressBar, + } = useEventCountdownProgressBar( + 'Dencun upgrade in progress', + ETH_DENCUN_START_DATE, + ETH_DENCUN_END_DATE + ) + return (
@@ -551,68 +565,77 @@ const StateManagedBridge = () => { -
- - - - - - - - - - - - - - - - - - - - - - - - - - - { - dispatch(setFromChainId(toChainId)) - dispatch(setFromToken(toToken)) - dispatch(setToChainId(fromChainId)) - dispatch(setToToken(fromToken)) - }} - /> - - - - - - {showDestinationAddress && ( - - )} -
- +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + { + dispatch(setFromChainId(toChainId)) + dispatch(setFromToken(toToken)) + dispatch(setToChainId(fromChainId)) + dispatch(setToToken(fromToken)) + }} /> + + + + + + {showDestinationAddress && ( + + )} +
+ +
diff --git a/packages/synapse-interface/public/blacklist.json b/packages/synapse-interface/public/blacklist.json index 52e4a9dd11..75ab13f5c3 100644 --- a/packages/synapse-interface/public/blacklist.json +++ b/packages/synapse-interface/public/blacklist.json @@ -421,5 +421,8 @@ "0xf2554a5f5F326D6A3453D5737B659b50658FfC93", "0x04969f79712bb2499b73733148e6e2bb46e27f94", "0xe874ae1a218c1a0d9983c908b587f029278b1c69", - "0xb59d04d9957c9e266dff5c4173d4d2324eb029ad" + "0xb59d04d9957c9e266dff5c4173d4d2324eb029ad", + "0xecb11a8180544228bedf38c5eb6c27729571ea3e", + "0x9961190B258897BCa7a12B8f37F415E689D281C4", + "0xe874Ae1a218C1A0d9983c908B587f029278B1C69" ] diff --git a/services/rfq/relayer/reldb/db.go b/services/rfq/relayer/reldb/db.go index f3af3ed0b7..44b5dd2ddd 100644 --- a/services/rfq/relayer/reldb/db.go +++ b/services/rfq/relayer/reldb/db.go @@ -92,6 +92,8 @@ func (q QuoteRequest) GetDestIDPair() string { // // TODO: consider making this an interface and exporting that. // +// EXTREMELY IMPORTANT: DO NOT ADD NEW VALUES TO THIS ENUM UNLESS THEY ARE AT THE END. +// //go:generate go run golang.org/x/tools/cmd/stringer -type=QuoteRequestStatus type QuoteRequestStatus uint8 @@ -123,6 +125,8 @@ const ( ClaimPending // ClaimCompleted means the relayer has called Claim() on the origin chain, and the tx has been confirmed on chain. ClaimCompleted + // RelayRaceLost means another relayer has relayed the tx. + RelayRaceLost ) // Int returns the int value of the quote request status. diff --git a/services/rfq/relayer/reldb/quoterequeststatus_string.go b/services/rfq/relayer/reldb/quoterequeststatus_string.go index 7ceddf9945..d3dc73c429 100644 --- a/services/rfq/relayer/reldb/quoterequeststatus_string.go +++ b/services/rfq/relayer/reldb/quoterequeststatus_string.go @@ -20,11 +20,12 @@ func _() { _ = x[ProvePosted-10] _ = x[ClaimPending-11] _ = x[ClaimCompleted-12] + _ = x[RelayRaceLost-13] } -const _QuoteRequestStatus_name = "SeenNotEnoughInventoryDeadlineExceededWillNotProcessCommittedPendingCommittedConfirmedRelayStartedRelayCompletedProvePostingProvePostedClaimPendingClaimCompleted" +const _QuoteRequestStatus_name = "SeenNotEnoughInventoryDeadlineExceededWillNotProcessCommittedPendingCommittedConfirmedRelayStartedRelayCompletedProvePostingProvePostedClaimPendingClaimCompletedRelayRaceLost" -var _QuoteRequestStatus_index = [...]uint8{0, 4, 22, 38, 52, 68, 86, 98, 112, 124, 135, 147, 161} +var _QuoteRequestStatus_index = [...]uint8{0, 4, 22, 38, 52, 68, 86, 98, 112, 124, 135, 147, 161, 174} func (i QuoteRequestStatus) String() string { i -= 1 diff --git a/services/rfq/relayer/service/chainindexer.go b/services/rfq/relayer/service/chainindexer.go index 41121c28f0..ec22be411c 100644 --- a/services/rfq/relayer/service/chainindexer.go +++ b/services/rfq/relayer/service/chainindexer.go @@ -78,7 +78,8 @@ func (r *Relayer) runChainIndexer(ctx context.Context, chainID int) (err error) case *fastbridge.FastBridgeBridgeRelayed: // it wasn't me if event.Relayer != r.signer.Address() { - return nil + //nolint: wrapcheck + return r.db.UpdateQuoteRequestStatus(ctx, event.TransactionId, reldb.RelayRaceLost) } err = r.handleRelayLog(ctx, event) @@ -88,7 +89,8 @@ func (r *Relayer) runChainIndexer(ctx context.Context, chainID int) (err error) case *fastbridge.FastBridgeBridgeProofProvided: // it wasn't me if event.Relayer != r.signer.Address() { - return nil + //nolint: wrapcheck + return r.db.UpdateQuoteRequestStatus(ctx, event.TransactionId, reldb.RelayRaceLost) } err = r.handleProofProvided(ctx, event) @@ -98,7 +100,8 @@ func (r *Relayer) runChainIndexer(ctx context.Context, chainID int) (err error) case *fastbridge.FastBridgeBridgeDepositClaimed: // it wasn't me if event.Relayer != r.signer.Address() { - return nil + //nolint: wrapcheck + return r.db.UpdateQuoteRequestStatus(ctx, event.TransactionId, reldb.RelayRaceLost) } err = r.handleDepositClaimed(ctx, event, chainID) From 0bad3fa3c5975edc1112839444b47f6af1b09219 Mon Sep 17 00:00:00 2001 From: aureliusbtc <82057759+aureliusbtc@users.noreply.github.com> Date: Wed, 13 Mar 2024 08:18:27 +0000 Subject: [PATCH 02/29] update bl --- packages/synapse-interface/public/blacklist.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/synapse-interface/public/blacklist.json b/packages/synapse-interface/public/blacklist.json index 75ab13f5c3..40a945926d 100644 --- a/packages/synapse-interface/public/blacklist.json +++ b/packages/synapse-interface/public/blacklist.json @@ -424,5 +424,6 @@ "0xb59d04d9957c9e266dff5c4173d4d2324eb029ad", "0xecb11a8180544228bedf38c5eb6c27729571ea3e", "0x9961190B258897BCa7a12B8f37F415E689D281C4", - "0xe874Ae1a218C1A0d9983c908B587f029278B1C69" + "0xe874Ae1a218C1A0d9983c908B587f029278B1C69", + "0xc12f2430ddfd54797533f827f78e49fe004d51a0" ] From 60ca5cd9ffa18507d90f1f7c4725d0310e655005 Mon Sep 17 00:00:00 2001 From: dwasse Date: Wed, 13 Mar 2024 14:57:26 -0500 Subject: [PATCH 03/29] Add MinRebalanceAmount to RFQ relayer (#2263) * Feat: add MinRebalanceAmount with tests * [goreleaser] * Fix: handle zero case * Feat: check for non positive amount outside of getRebalance() * Cleanup: lint * Cleanup: utilize getTokenConfig() helper * [goreleaser] * update godoc [goreleaser] * Cleanup: lint * Fix: don't rebalance if desired amount less than min --------- Co-authored-by: Trajan0x --- services/rfq/relayer/inventory/manager.go | 14 +++++-- .../rfq/relayer/inventory/manager_test.go | 22 ++++++++-- services/rfq/relayer/relconfig/config.go | 3 ++ services/rfq/relayer/relconfig/getters.go | 40 ++++++++++++------- 4 files changed, 59 insertions(+), 20 deletions(-) diff --git a/services/rfq/relayer/inventory/manager.go b/services/rfq/relayer/inventory/manager.go index 658d1a7220..abd131542a 100644 --- a/services/rfq/relayer/inventory/manager.go +++ b/services/rfq/relayer/inventory/manager.go @@ -370,7 +370,7 @@ func (i *inventoryManagerImpl) Rebalance(parentCtx context.Context, chainID int, if err != nil { return fmt.Errorf("could not get rebalance: %w", err) } - if rebalance == nil { + if rebalance == nil || rebalance.Amount.Cmp(big.NewInt(0)) <= 0 { return nil } span.SetAttributes( @@ -466,8 +466,16 @@ func getRebalance(span trace.Span, cfg relconfig.Config, tokens map[int]map[comm initialThresh, _ := new(big.Float).Mul(new(big.Float).SetInt(totalBalance), big.NewFloat(initialPct/100)).Int(nil) amount := new(big.Int).Sub(maxTokenData.Balance, initialThresh) - // no need to rebalance since amount would be negative - if amount.Cmp(big.NewInt(0)) < 0 { + // no need to rebalance since amount would not be positive + if amount.Cmp(big.NewInt(0)) <= 0 { + //nolint:nilnil + return nil, nil + } + + // filter the rebalance amount by the configured min + minAmount := cfg.GetMinRebalanceAmount(maxTokenData.ChainID, maxTokenData.Addr) + if amount.Cmp(minAmount) < 0 { + // no need to rebalance //nolint:nilnil return nil, nil } diff --git a/services/rfq/relayer/inventory/manager_test.go b/services/rfq/relayer/inventory/manager_test.go index 11d33709f6..84444a2c5f 100644 --- a/services/rfq/relayer/inventory/manager_test.go +++ b/services/rfq/relayer/inventory/manager_test.go @@ -88,7 +88,7 @@ func (i *InventoryTestSuite) TestGetRebalance() { usdcDataDest.Addr: &usdcDataDest, }, } - getConfig := func(maxRebalanceAmount string) relconfig.Config { + getConfig := func(minRebalanceAmount, maxRebalanceAmount string) relconfig.Config { return relconfig.Config{ Chains: map[int]relconfig.ChainConfig{ origin: { @@ -98,6 +98,7 @@ func (i *InventoryTestSuite) TestGetRebalance() { Decimals: 6, MaintenanceBalancePct: 20, InitialBalancePct: 50, + MinRebalanceAmount: minRebalanceAmount, MaxRebalanceAmount: maxRebalanceAmount, }, }, @@ -109,6 +110,7 @@ func (i *InventoryTestSuite) TestGetRebalance() { Decimals: 6, MaintenanceBalancePct: 20, InitialBalancePct: 50, + MinRebalanceAmount: minRebalanceAmount, MaxRebalanceAmount: maxRebalanceAmount, }, }, @@ -120,6 +122,7 @@ func (i *InventoryTestSuite) TestGetRebalance() { Decimals: 6, MaintenanceBalancePct: 0, InitialBalancePct: 0, + MinRebalanceAmount: minRebalanceAmount, MaxRebalanceAmount: maxRebalanceAmount, }, }, @@ -129,13 +132,20 @@ func (i *InventoryTestSuite) TestGetRebalance() { } // 10 USDC on both chains; no rebalance needed - cfg := getConfig("") + cfg := getConfig("", "") usdcDataOrigin.Balance = big.NewInt(1e7) usdcDataDest.Balance = big.NewInt(1e7) rebalance, err := inventory.GetRebalance(cfg, tokens, origin, usdcDataOrigin.Addr) i.NoError(err) i.Nil(rebalance) + // Set balances to zero + usdcDataOrigin.Balance = big.NewInt(0) + usdcDataDest.Balance = big.NewInt(0) + rebalance, err = inventory.GetRebalance(cfg, tokens, origin, usdcDataOrigin.Addr) + i.NoError(err) + i.Nil(rebalance) + // Set origin balance below maintenance threshold; need rebalance usdcDataOrigin.Balance = big.NewInt(9e6) usdcDataDest.Balance = big.NewInt(1e6) @@ -148,8 +158,14 @@ func (i *InventoryTestSuite) TestGetRebalance() { } i.Equal(expected, rebalance) + // Set min rebalance amount + cfgWithMax := getConfig("10", "1000000000") + rebalance, err = inventory.GetRebalance(cfgWithMax, tokens, origin, usdcDataOrigin.Addr) + i.NoError(err) + i.Nil(rebalance) + // Set max rebalance amount - cfgWithMax := getConfig("1.1") + cfgWithMax = getConfig("0", "1.1") rebalance, err = inventory.GetRebalance(cfgWithMax, tokens, origin, usdcDataOrigin.Addr) i.NoError(err) expected = &inventory.RebalanceData{ diff --git a/services/rfq/relayer/relconfig/config.go b/services/rfq/relayer/relconfig/config.go index 12d3cb7ef6..864275e7bc 100644 --- a/services/rfq/relayer/relconfig/config.go +++ b/services/rfq/relayer/relconfig/config.go @@ -102,6 +102,9 @@ type TokenConfig struct { MaintenanceBalancePct float64 `yaml:"maintenance_balance_pct"` // InitialBalancePct is the percentage of the total balance to retain when triggering a rebalance. InitialBalancePct float64 `yaml:"initial_balance_pct"` + // MinRebalanceAmount is the minimum amount to rebalance in human-readable units. + // For USDC-through-cctp pairs this defaults to $1,000. + MinRebalanceAmount string `yaml:"min_rebalance_amount"` // MaxRebalanceAmount is the maximum amount to rebalance in human-readable units. MaxRebalanceAmount string `yaml:"max_rebalance_amount"` } diff --git a/services/rfq/relayer/relconfig/getters.go b/services/rfq/relayer/relconfig/getters.go index 2e0b5362de..afc0c1d80c 100644 --- a/services/rfq/relayer/relconfig/getters.go +++ b/services/rfq/relayer/relconfig/getters.go @@ -547,25 +547,37 @@ func (c Config) GetMinQuoteAmount(chainID int, addr common.Address) *big.Int { return quoteAmountScaled } -var defaultMaxRebalanceAmount = abi.MaxInt256 +var defaultMinRebalanceAmount = big.NewInt(1000) -// GetMaxRebalanceAmount returns the max rebalance amount for the given chain and address. +// GetMinRebalanceAmount returns the min rebalance amount for the given chain and address. // Note that this getter returns the value in native token decimals. -func (c Config) GetMaxRebalanceAmount(chainID int, addr common.Address) *big.Int { - chainCfg, ok := c.Chains[chainID] - if !ok { +// +//nolint:dupl +func (c Config) GetMinRebalanceAmount(chainID int, addr common.Address) *big.Int { + tokenCfg, _, err := c.getTokenConfigByAddr(chainID, addr.Hex()) + if err != nil { return defaultMaxRebalanceAmount } - - var tokenCfg *TokenConfig - for _, cfg := range chainCfg.Tokens { - if common.HexToAddress(cfg.Address).Hex() == addr.Hex() { - cfgCopy := cfg - tokenCfg = &cfgCopy - break - } + rebalanceAmountFlt, ok := new(big.Float).SetString(tokenCfg.MinRebalanceAmount) + if !ok || rebalanceAmountFlt == nil { + return defaultMinRebalanceAmount } - if tokenCfg == nil { + + // Scale by the token decimals. + denomDecimalsFactor := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(tokenCfg.Decimals)), nil) + minRebalanceAmountScaled, _ := new(big.Float).Mul(rebalanceAmountFlt, new(big.Float).SetInt(denomDecimalsFactor)).Int(nil) + return minRebalanceAmountScaled +} + +var defaultMaxRebalanceAmount = abi.MaxInt256 + +// GetMaxRebalanceAmount returns the max rebalance amount for the given chain and address. +// Note that this getter returns the value in native token decimals. +// +//nolint:dupl +func (c Config) GetMaxRebalanceAmount(chainID int, addr common.Address) *big.Int { + tokenCfg, _, err := c.getTokenConfigByAddr(chainID, addr.Hex()) + if err != nil { return defaultMaxRebalanceAmount } rebalanceAmountFlt, ok := new(big.Float).SetString(tokenCfg.MaxRebalanceAmount) From f527ce53c883672232f43da90f0614a8a580442a Mon Sep 17 00:00:00 2001 From: bigboydiamonds <57741810+bigboydiamonds@users.noreply.github.com> Date: Wed, 13 Mar 2024 13:56:20 -0700 Subject: [PATCH 04/29] feat(synapse-interface): ecotone and metis upgrade downtime, remove eth dencun (#2274) * Add Ecotone Fork upgrade banner * Add Metis Downtime banner * Add Banner * Remove ETH Dencun annoucements * Add Ecotone Fork and Metis Upgrade Countdown Progress Bar to Bridge card * Implement Bridge pauses for Metis and Ecotone downtime * Bridge Pause feature working * Add Ecotone Fork upgrade message * Improve Ecotone Fork warning message * Update Metis downtime message * Simplify comparisons * Update ecotone warning message * Clean, prep for merge * Update id * Update EcotoneFork end time * Move Events into Events folder * Update Metis banner * Update Ecotone Banner for EST * Set times * Rm import * useEcotoneForkEventCountdownProgress to determine when to display progress * useMetisDowntimeCountdownProgress * Add isCurrentChainDisabled props * Replace isBridgePaused with chain disabled prop * Clean * getCountdownTimeStatus * Clean * calculateTimeUntilTarget to be used in getCountdownTimeStatus * Show hours remaining when over 90 min * Update var naming * Clean * Update id to prevent conflicts * Automatically show and remove Banner based on start / end time * Refactor: AnnouncementBanner to use getCountdownTimeStatus * Automate Banners to appear / disappear after start / end time respectively * Keep in sync interval timers across all event countdown components * Add comments * adjust timings --------- Co-authored-by: aureliusbtc <82057759+aureliusbtc@users.noreply.github.com> --- .../Maintenance/AnnouncementBanner.tsx | 19 +- .../Maintenance/EthDencunUpgrade.tsx | 30 ---- .../Maintenance/EventCountdownProgressBar.tsx | 109 ++++++++--- .../Maintenance/Events/EcotoneForkUpgrade.tsx | 93 ++++++++++ .../Maintenance/Events/MetisUpgrade.tsx | 90 ++++++++++ .../Maintenance/LinearAnimatedProgressBar.tsx | 31 ++-- packages/synapse-interface/pages/index.tsx | 6 +- .../pages/state-managed-bridge/index.tsx | 169 ++++++++++-------- .../utils/hooks/useIntervalTimer.ts | 24 ++- 9 files changed, 402 insertions(+), 169 deletions(-) delete mode 100644 packages/synapse-interface/components/Maintenance/EthDencunUpgrade.tsx create mode 100644 packages/synapse-interface/components/Maintenance/Events/EcotoneForkUpgrade.tsx create mode 100644 packages/synapse-interface/components/Maintenance/Events/MetisUpgrade.tsx diff --git a/packages/synapse-interface/components/Maintenance/AnnouncementBanner.tsx b/packages/synapse-interface/components/Maintenance/AnnouncementBanner.tsx index 42dc33dc97..377bcfadcf 100644 --- a/packages/synapse-interface/components/Maintenance/AnnouncementBanner.tsx +++ b/packages/synapse-interface/components/Maintenance/AnnouncementBanner.tsx @@ -1,7 +1,10 @@ import { useState, useEffect } from 'react' +import { getCountdownTimeStatus } from './EventCountdownProgressBar' /** - * Reusable Annoucement Banner with custom Start/End Time + * Reusable automated Announcement Banner with custom Start/End Time + * Will automatically appear after Start time + * Will automatically disappear after End time * @param bannerId: store in $MMDDYYYY-$BANNER_NAME format (e.g 03132024-ETH-DENCUN) * @param bannerContents: contents to display in banner * @param startDate: start date to show banner @@ -18,15 +21,9 @@ export const AnnouncementBanner = ({ startDate: Date endDate: Date }) => { + const { isStarted, isComplete } = getCountdownTimeStatus(startDate, endDate) const [hasMounted, setHasMounted] = useState(false) - const [showBanner, setShowBanner] = useState(false) - - const currentDate = new Date() - - const isStarted = - Math.floor(currentDate.getTime()) - Math.floor(startDate.getTime()) >= 0 - const isComplete = - Math.floor(currentDate.getTime()) - Math.floor(endDate.getTime()) >= 0 + const [showBanner, setShowBanner] = useState(true) useEffect(() => { setHasMounted(true) @@ -54,11 +51,11 @@ export const AnnouncementBanner = ({ } }, [showBanner, hasMounted]) - if (!showBanner || !hasMounted || isComplete) return null + if (!showBanner || !hasMounted || !isStarted || isComplete) return null return (
{ - return ( - -
- Synapse Bridge is upgrading ahead of the Ethereum Dencun upgrade - (March 13, 13:55 UTC, 9:55 EST). -
-
Will be back online shortly ahead of the network upgrade.
-
- } - startDate={ETH_DENCUN_BANNER_START} - endDate={ETH_DENCUN_END_DATE} - /> - ) -} diff --git a/packages/synapse-interface/components/Maintenance/EventCountdownProgressBar.tsx b/packages/synapse-interface/components/Maintenance/EventCountdownProgressBar.tsx index b4f60eb5ba..c2e9a9c41a 100644 --- a/packages/synapse-interface/components/Maintenance/EventCountdownProgressBar.tsx +++ b/packages/synapse-interface/components/Maintenance/EventCountdownProgressBar.tsx @@ -1,4 +1,3 @@ -import { useMemo } from 'react' import { LinearAnimatedProgressBar } from './LinearAnimatedProgressBar' import { useIntervalTimer } from '@/utils/hooks/useIntervalTimer' @@ -12,17 +11,14 @@ export const useEventCountdownProgressBar = ( EventCountdownProgressBar: JSX.Element } => { useIntervalTimer(60000) - const currentDate = new Date() - const currentTimeInSeconds = currentDate.getTime() / 1000 - const startTimeInSeconds = Math.floor(startDate.getTime() / 1000) - const endTimeInSeconds = Math.floor(endDate.getTime() / 1000) - const timeRemainingInSeconds = endTimeInSeconds - currentTimeInSeconds - const timeRemainingInMinutes = Math.ceil(timeRemainingInSeconds / 60) + const { totalTimeRemainingInMinutes, hoursRemaining, isComplete, isPending } = + getCountdownTimeStatus(startDate, endDate) - const isStarted = currentTimeInSeconds >= startTimeInSeconds - const isComplete = timeRemainingInSeconds <= 0 - const isPending = isStarted && !isComplete + const timeRemaining: string = + totalTimeRemainingInMinutes > 90 + ? `${hoursRemaining}h` + : `${totalTimeRemainingInMinutes}min` let status: 'idle' | 'pending' | 'complete' @@ -40,10 +36,10 @@ export const useEventCountdownProgressBar = ( EventCountdownProgressBar: ( ), } @@ -51,16 +47,16 @@ export const useEventCountdownProgressBar = ( export const EventCountdownProgressBar = ({ eventLabel, - startTime, - endTime, - status, + startDate, + endDate, timeRemaining, + status, }: { eventLabel: string - startTime: number - endTime: number + startDate: Date + endDate: Date + timeRemaining: string status: 'idle' | 'pending' | 'complete' - timeRemaining: number }) => { if (status === 'pending') { return ( @@ -73,14 +69,13 @@ export const EventCountdownProgressBar = ({ >
{eventLabel}
-
{timeRemaining}m remaining
+
{timeRemaining} remaining
@@ -89,3 +84,69 @@ export const EventCountdownProgressBar = ({ return null } } + +export const getCountdownTimeStatus = (startDate: Date, endDate: Date) => { + const currentDate = new Date() + + const { daysRemaining, hoursRemaining, minutesRemaining, secondsRemaining } = + calculateTimeUntilTarget(endDate) + + const currentTimeInSeconds = Math.floor(currentDate.getTime() / 1000) + + const startTimeInSeconds = Math.floor(startDate.getTime() / 1000) + const endTimeInSeconds = Math.floor(endDate.getTime() / 1000) + const totalTimeInSeconds = endTimeInSeconds - startTimeInSeconds + + const totalTimeElapsedInSeconds = currentTimeInSeconds - startTimeInSeconds + const totalTimeRemainingInSeconds = endTimeInSeconds - currentTimeInSeconds + const totalTimeRemainingInMinutes = Math.ceil( + totalTimeRemainingInSeconds / 60 + ) + + const isStarted = currentTimeInSeconds >= startTimeInSeconds + const isComplete = totalTimeRemainingInSeconds <= 0 + const isPending = isStarted && !isComplete + + return { + currentDate, + currentTimeInSeconds, + startTimeInSeconds, + endTimeInSeconds, + totalTimeInSeconds, + totalTimeElapsedInSeconds, + totalTimeRemainingInSeconds, + totalTimeRemainingInMinutes, + daysRemaining, + hoursRemaining, + minutesRemaining, + secondsRemaining, + isStarted, + isComplete, + isPending, + } +} + +const calculateTimeUntilTarget = (targetDate: Date) => { + const currentDate = new Date() + + const timeDifference = targetDate.getTime() - currentDate.getTime() + + const isComplete = timeDifference <= 0 + + const daysRemaining = Math.floor(timeDifference / (1000 * 60 * 60 * 24)) + const hoursRemaining = Math.floor( + (timeDifference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60) + ) + const minutesRemaining = Math.floor( + (timeDifference % (1000 * 60 * 60)) / (1000 * 60) + ) + const secondsRemaining = Math.floor((timeDifference % (1000 * 60)) / 1000) + + return { + daysRemaining, + hoursRemaining, + minutesRemaining, + secondsRemaining, + isComplete, + } +} diff --git a/packages/synapse-interface/components/Maintenance/Events/EcotoneForkUpgrade.tsx b/packages/synapse-interface/components/Maintenance/Events/EcotoneForkUpgrade.tsx new file mode 100644 index 0000000000..c2dd3dd355 --- /dev/null +++ b/packages/synapse-interface/components/Maintenance/Events/EcotoneForkUpgrade.tsx @@ -0,0 +1,93 @@ +import { AnnouncementBanner } from '../AnnouncementBanner' +import { WarningMessage } from '../../Warning' +import { useBridgeState } from '@/slices/bridge/hooks' +import { OPTIMISM, BASE } from '@/constants/chains/master' +import { + useEventCountdownProgressBar, + getCountdownTimeStatus, +} from '../EventCountdownProgressBar' +import { useIntervalTimer } from '@/utils/hooks/useIntervalTimer' + +/** + * Start: 25 min prior to Ecotone Fork Upgrade Time @ (March 14, 00:00 UTC) + * End: 25 min after start of Ecotone Fork Upgrade Time + */ +export const ECOTONE_FORK_BANNERS_START = new Date( + Date.UTC(2024, 2, 13, 23, 20, 0) +) +export const ECOTONE_FORK_START_DATE = new Date( + Date.UTC(2024, 2, 13, 23, 35, 0) +) +export const ECOTONE_FORK_END_DATE = new Date(Date.UTC(2024, 2, 14, 0, 25, 0)) + +export const EcotoneForkUpgradeBanner = () => { + const { isComplete } = getCountdownTimeStatus( + ECOTONE_FORK_BANNERS_START, + ECOTONE_FORK_END_DATE + ) + + useIntervalTimer(60000, isComplete) + + return ( + +
+ Optimism + Base Bridging will be paused 10 minutes ahead of Ecotone + (March 14, 00:00 UTC, 20:00 EST). +
+
Will be back online shortly following the network upgrade.
+
+ } + startDate={ECOTONE_FORK_BANNERS_START} + endDate={ECOTONE_FORK_END_DATE} + /> + ) +} + +export const EcotoneForkWarningMessage = () => { + const { fromChainId, toChainId } = useBridgeState() + + const isChainOptimism = [fromChainId, toChainId].includes(OPTIMISM.id) + const isChainBase = [fromChainId, toChainId].includes(BASE.id) + + if (isChainOptimism || isChainBase) { + return ( + +

+ Optimism Chain and Base Chain bridging are paused until the + Ecotone Fork upgrade completes. +

+ + } + /> + ) + } else return null +} + +export const useEcotoneForkCountdownProgress = () => { + const { fromChainId, toChainId } = useBridgeState() + + const isChainOptimism = [fromChainId, toChainId].includes(OPTIMISM.id) + const isChainBase = [fromChainId, toChainId].includes(BASE.id) + + const { + isPending: isEcotoneForkUpgradePending, + EventCountdownProgressBar: EcotoneForkCountdownProgressBar, + } = useEventCountdownProgressBar( + 'Ecotone Fork upgrade in progress', + ECOTONE_FORK_START_DATE, + ECOTONE_FORK_END_DATE + ) + + return { + isEcotoneForkUpgradePending, + isCurrentChainDisabled: + (isChainOptimism || isChainBase) && isEcotoneForkUpgradePending, + EcotoneForkCountdownProgressBar: + isChainOptimism || isChainBase ? EcotoneForkCountdownProgressBar : null, + } +} diff --git a/packages/synapse-interface/components/Maintenance/Events/MetisUpgrade.tsx b/packages/synapse-interface/components/Maintenance/Events/MetisUpgrade.tsx new file mode 100644 index 0000000000..20272264af --- /dev/null +++ b/packages/synapse-interface/components/Maintenance/Events/MetisUpgrade.tsx @@ -0,0 +1,90 @@ +import { AnnouncementBanner } from '../AnnouncementBanner' +import { WarningMessage } from '../../Warning' +import { useBridgeState } from '@/slices/bridge/hooks' +import { METIS } from '@/constants/chains/master' +import { useEventCountdownProgressBar } from '../EventCountdownProgressBar' +import { useIntervalTimer } from '@/utils/hooks/useIntervalTimer' +import { getCountdownTimeStatus } from '../EventCountdownProgressBar' + +/** + * Start: 30 min prior to Metis Chain Downtime @ (March 14, 02:00 UTC) + * End: 12 hours after start of Metis Chain Downtime + */ +export const METIS_DOWNTIME_BANNERS_START = new Date( + Date.UTC(2024, 2, 14, 1, 30, 0) +) +export const METIS_DOWNTIME_START_DATE = new Date( + Date.UTC(2024, 2, 14, 1, 45, 0) +) +export const METIS_DOWNTIME_END_DATE = new Date( + Date.UTC(2024, 2, 14, 13, 30, 0) +) + +export const MetisDowntimeBanner = () => { + const { isComplete } = getCountdownTimeStatus( + METIS_DOWNTIME_BANNERS_START, + METIS_DOWNTIME_END_DATE + ) + + useIntervalTimer(60000, isComplete) + + return ( + +
+ Metis Chain bridging will be paused 30 min ahead of the Metis + Upgrade (March 14, 02:00 UTC, 22:00 EST) +
+
and stay paused for ~12 hours.
+
+ } + startDate={METIS_DOWNTIME_BANNERS_START} + endDate={METIS_DOWNTIME_END_DATE} + /> + ) +} + +export const MetisDowntimeWarningMessage = () => { + const { fromChainId, toChainId } = useBridgeState() + + const isChainMetis = [fromChainId, toChainId].includes(METIS.id) + + if (isChainMetis) { + return ( + +

+ Metis Chain bridging is paused until the Metis upgrade completes. +

+ + } + /> + ) + } else return null +} + +export const useMetisDowntimeCountdownProgress = () => { + const { fromChainId, toChainId } = useBridgeState() + + const isChainMetis = [fromChainId, toChainId].includes(METIS.id) + + const { + isPending: isMetisUpgradePending, + EventCountdownProgressBar: MetisUpgradeCountdownProgressBar, + } = useEventCountdownProgressBar( + 'Metis upgrade in progress', + METIS_DOWNTIME_START_DATE, + METIS_DOWNTIME_END_DATE + ) + + return { + isMetisUpgradePending, + isCurrentChainDisabled: isChainMetis && isMetisUpgradePending, + MetisUpgradeCountdownProgressBar: isChainMetis + ? MetisUpgradeCountdownProgressBar + : null, + } +} diff --git a/packages/synapse-interface/components/Maintenance/LinearAnimatedProgressBar.tsx b/packages/synapse-interface/components/Maintenance/LinearAnimatedProgressBar.tsx index d2c90fbe7b..955b932afc 100644 --- a/packages/synapse-interface/components/Maintenance/LinearAnimatedProgressBar.tsx +++ b/packages/synapse-interface/components/Maintenance/LinearAnimatedProgressBar.tsx @@ -1,36 +1,33 @@ import { memo } from 'react' -import { getTimeMinutesBeforeNow } from '@/utils/time' +import { getCountdownTimeStatus } from './EventCountdownProgressBar' /** * @param id unique identifier for progress bar instance * @param startTime start time in unix seconds * @param endTime end time in unix seconds - * @param status progress status */ export const LinearAnimatedProgressBar = memo( ({ id, - startTime, - endTime, - status, + startDate, + endDate, }: { id: string - startTime: number - endTime: number - status: 'idle' | 'pending' | 'complete' + startDate: Date + endDate: Date }) => { - const currentTime = Math.floor(getTimeMinutesBeforeNow(0)) - const elapsedTimeInSeconds = currentTime - startTime - const remainingTimeInSeconds = endTime - currentTime - const totalTimeInSeconds = endTime - startTime + const { + totalTimeInSeconds, + totalTimeElapsedInSeconds, + totalTimeRemainingInSeconds, + isComplete, + } = getCountdownTimeStatus(startDate, endDate) const percentElapsed = Math.floor( - (elapsedTimeInSeconds / totalTimeInSeconds) * 100 + (totalTimeElapsedInSeconds / totalTimeInSeconds) * 100 ) - const isComplete = status === 'complete' - - let duration = isComplete ? 0.5 : remainingTimeInSeconds + let duration = isComplete ? 0.5 : totalTimeRemainingInSeconds const synapsePurple = 'hsl(265deg 100% 75%)' const tailwindGreen400 = 'rgb(74 222 128)' @@ -40,7 +37,7 @@ export const LinearAnimatedProgressBar = memo( return ( { data-test-id="bridge-page" className="relative z-0 flex-1 h-full overflow-y-auto focus:outline-none" > - + +
diff --git a/packages/synapse-interface/pages/state-managed-bridge/index.tsx b/packages/synapse-interface/pages/state-managed-bridge/index.tsx index f23db2701e..9cb71d6685 100644 --- a/packages/synapse-interface/pages/state-managed-bridge/index.tsx +++ b/packages/synapse-interface/pages/state-managed-bridge/index.tsx @@ -87,10 +87,21 @@ import { import { isTransactionReceiptError } from '@/utils/isTransactionReceiptError' import { SwitchButton } from '@/components/buttons/SwitchButton' import { useEventCountdownProgressBar } from '@/components/Maintenance/EventCountdownProgressBar' + +import { + METIS_DOWNTIME_START_DATE, + METIS_DOWNTIME_END_DATE, + MetisDowntimeWarningMessage, + useMetisDowntimeCountdownProgress, +} from '@/components/Maintenance/Events/MetisUpgrade' import { - ETH_DENCUN_START_DATE, - ETH_DENCUN_END_DATE, -} from '@/components/Maintenance/EthDencunUpgrade' + ECOTONE_FORK_START_DATE, + ECOTONE_FORK_END_DATE, + EcotoneForkWarningMessage, + useEcotoneForkCountdownProgress, +} from '@/components/Maintenance/Events/EcotoneForkUpgrade' + +import { OPTIMISM, BASE, METIS } from '@/constants/chains/master' const StateManagedBridge = () => { const { address } = useAccount() @@ -523,14 +534,19 @@ const StateManagedBridge = () => { const springClass = '-mt-4 fixed z-50 w-full h-full bg-opacity-50 bg-[#343036]' + /* Remove after upgrades */ const { - isPending: isUpgradePending, - EventCountdownProgressBar: EthDencunEventCountdownProgressBar, - } = useEventCountdownProgressBar( - 'Dencun upgrade in progress', - ETH_DENCUN_START_DATE, - ETH_DENCUN_END_DATE - ) + isEcotoneForkUpgradePending, + isCurrentChainDisabled: isEcotoneUpgradeChainsDisabled, + EcotoneForkCountdownProgressBar, + } = useEcotoneForkCountdownProgress() + + const { + isMetisUpgradePending, + isCurrentChainDisabled: isMetisUpgradeChainDisabled, + MetisUpgradeCountdownProgressBar, + } = useMetisDowntimeCountdownProgress() + /* Remove after upgrades */ return (
@@ -569,73 +585,74 @@ const StateManagedBridge = () => { transition-all duration-100 transform rounded-md `} > - {EthDencunEventCountdownProgressBar} -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - { - dispatch(setFromChainId(toChainId)) - dispatch(setFromToken(toToken)) - dispatch(setToChainId(fromChainId)) - dispatch(setToToken(fromToken)) - }} + {EcotoneForkCountdownProgressBar} + {MetisUpgradeCountdownProgressBar} +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + { + dispatch(setFromChainId(toChainId)) + dispatch(setFromToken(toToken)) + dispatch(setToChainId(fromChainId)) + dispatch(setToToken(fromToken)) + }} + /> + + + + {/* Remove after upgrades */} + {isEcotoneForkUpgradePending && } + {isMetisUpgradePending && } + {/* Remove after upgrades */} + + + + + {showDestinationAddress && ( + + )} +
+ - - - - - - {showDestinationAddress && ( - - )} -
- -
diff --git a/packages/synapse-interface/utils/hooks/useIntervalTimer.ts b/packages/synapse-interface/utils/hooks/useIntervalTimer.ts index c394bff315..c84a5d07e9 100644 --- a/packages/synapse-interface/utils/hooks/useIntervalTimer.ts +++ b/packages/synapse-interface/utils/hooks/useIntervalTimer.ts @@ -6,24 +6,30 @@ import { getTimeMinutesFromNow } from '@/utils/time' * Hook for setting an interval based timer * * @param intervalInMs number, in ms (1000ms = 1s) + * @param isDisabled boolean, determines if we update at intervals * returns current time in minutes, unix */ -export const useIntervalTimer = (intervalInMs: number) => { +export const useIntervalTimer = ( + intervalInMs: number, + isDisabled?: boolean +) => { const [currentTime, setCurrentTime] = useState( getTimeMinutesFromNow(0) ) - /** Update time at set intervals */ + /** Update time at set intervals if not disabled */ useEffect(() => { - const interval = setInterval(() => { - const newCurrentTime = getTimeMinutesFromNow(0) - setCurrentTime(newCurrentTime) - }, intervalInMs) + if (!isDisabled) { + const interval = setInterval(() => { + const newCurrentTime = getTimeMinutesFromNow(0) + setCurrentTime(newCurrentTime) + }, intervalInMs) - return () => { - clearInterval(interval) // Clear the interval when the component unmounts + return () => { + clearInterval(interval) // Clear the interval when the component unmounts + } } - }, []) + }, [isDisabled]) return currentTime } From 986cf60eba979418e22456a40a03b99bac8bed95 Mon Sep 17 00:00:00 2001 From: bigboydiamonds Date: Wed, 13 Mar 2024 20:59:45 +0000 Subject: [PATCH 05/29] Publish - @synapsecns/synapse-interface@0.8.0 --- packages/synapse-interface/CHANGELOG.md | 11 +++++++++++ packages/synapse-interface/package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/synapse-interface/CHANGELOG.md b/packages/synapse-interface/CHANGELOG.md index 7b39baddcb..83179f0c98 100644 --- a/packages/synapse-interface/CHANGELOG.md +++ b/packages/synapse-interface/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.8.0](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.7.1...@synapsecns/synapse-interface@0.8.0) (2024-03-13) + + +### Features + +* **synapse-interface:** ecotone and metis upgrade downtime, remove eth dencun ([#2274](https://github.com/synapsecns/sanguine/issues/2274)) ([f527ce5](https://github.com/synapsecns/sanguine/commit/f527ce53c883672232f43da90f0614a8a580442a)) + + + + + ## [0.7.1](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.7.0...@synapsecns/synapse-interface@0.7.1) (2024-03-13) **Note:** Version bump only for package @synapsecns/synapse-interface diff --git a/packages/synapse-interface/package.json b/packages/synapse-interface/package.json index c9f0feae6c..ef3d9b4a98 100644 --- a/packages/synapse-interface/package.json +++ b/packages/synapse-interface/package.json @@ -1,6 +1,6 @@ { "name": "@synapsecns/synapse-interface", - "version": "0.7.1", + "version": "0.8.0", "private": true, "engines": { "node": ">=16.0.0" From 45fbfdc245647b8db87b889e252fa4aece49f501 Mon Sep 17 00:00:00 2001 From: bigboydiamonds <57741810+bigboydiamonds@users.noreply.github.com> Date: Wed, 13 Mar 2024 14:00:49 -0700 Subject: [PATCH 06/29] feat(synapse-interface): use both rebate displays in bridge card (#2276) * Use prior rebate version * Show both rebate versions --- .../components/StateManagedBridge/BridgeExchangeRateInfo.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/synapse-interface/components/StateManagedBridge/BridgeExchangeRateInfo.tsx b/packages/synapse-interface/components/StateManagedBridge/BridgeExchangeRateInfo.tsx index 0824226296..2e21afa2df 100644 --- a/packages/synapse-interface/components/StateManagedBridge/BridgeExchangeRateInfo.tsx +++ b/packages/synapse-interface/components/StateManagedBridge/BridgeExchangeRateInfo.tsx @@ -19,8 +19,8 @@ const MAX_ARB_REBATE_PER_ADDRESS = 2000 const BridgeExchangeRateInfo = () => { return (
- {/* */} - + + {/* */}
From c6675178f6066ab43f6c82f672cf8deeb27b54e0 Mon Sep 17 00:00:00 2001 From: bigboydiamonds <57741810+bigboydiamonds@users.noreply.github.com> Date: Wed, 13 Mar 2024 14:02:59 -0700 Subject: [PATCH 07/29] Use prior rebate version (#2275) --- .../components/StateManagedBridge/BridgeExchangeRateInfo.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/synapse-interface/components/StateManagedBridge/BridgeExchangeRateInfo.tsx b/packages/synapse-interface/components/StateManagedBridge/BridgeExchangeRateInfo.tsx index 2e21afa2df..af6f4f79c5 100644 --- a/packages/synapse-interface/components/StateManagedBridge/BridgeExchangeRateInfo.tsx +++ b/packages/synapse-interface/components/StateManagedBridge/BridgeExchangeRateInfo.tsx @@ -24,7 +24,7 @@ const BridgeExchangeRateInfo = () => {
- + {/* */}
From 13d56abe53f8b6370cb1fc362a416306e64a9c65 Mon Sep 17 00:00:00 2001 From: bigboydiamonds Date: Wed, 13 Mar 2024 21:06:55 +0000 Subject: [PATCH 08/29] Publish - @synapsecns/synapse-interface@0.9.0 --- packages/synapse-interface/CHANGELOG.md | 11 +++++++++++ packages/synapse-interface/package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/synapse-interface/CHANGELOG.md b/packages/synapse-interface/CHANGELOG.md index 83179f0c98..27e646a1eb 100644 --- a/packages/synapse-interface/CHANGELOG.md +++ b/packages/synapse-interface/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.9.0](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.8.0...@synapsecns/synapse-interface@0.9.0) (2024-03-13) + + +### Features + +* **synapse-interface:** use both rebate displays in bridge card ([#2276](https://github.com/synapsecns/sanguine/issues/2276)) ([45fbfdc](https://github.com/synapsecns/sanguine/commit/45fbfdc245647b8db87b889e252fa4aece49f501)) + + + + + # [0.8.0](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.7.1...@synapsecns/synapse-interface@0.8.0) (2024-03-13) diff --git a/packages/synapse-interface/package.json b/packages/synapse-interface/package.json index ef3d9b4a98..6c19f1856c 100644 --- a/packages/synapse-interface/package.json +++ b/packages/synapse-interface/package.json @@ -1,6 +1,6 @@ { "name": "@synapsecns/synapse-interface", - "version": "0.8.0", + "version": "0.9.0", "private": true, "engines": { "node": ">=16.0.0" From 552d1c32a8430fc02f0dc19bb5f15b581ef62ccf Mon Sep 17 00:00:00 2001 From: bigboydiamonds <57741810+bigboydiamonds@users.noreply.github.com> Date: Wed, 13 Mar 2024 15:15:29 -0700 Subject: [PATCH 09/29] Fe/resolve fe release conflicts (#2280) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * FE Release 2024-03-12 (#2271) * Add Ecotone Fork upgrade banner * Add Metis Downtime banner * Add Banner * Remove ETH Dencun annoucements * Add Ecotone Fork and Metis Upgrade Countdown Progress Bar to Bridge card * Implement Bridge pauses for Metis and Ecotone downtime * Bridge Pause feature working * Add Ecotone Fork upgrade message * Improve Ecotone Fork warning message * Update Metis downtime message * Simplify comparisons * Update ecotone warning message * Clean, prep for merge * Update id * Update EcotoneFork end time * Move Events into Events folder * Update Metis banner * Update Ecotone Banner for EST * Set times * Rm import * useEcotoneForkEventCountdownProgress to determine when to display progress * useMetisDowntimeCountdownProgress * Add isCurrentChainDisabled props * Replace isBridgePaused with chain disabled prop * Clean * getCountdownTimeStatus * Clean * calculateTimeUntilTarget to be used in getCountdownTimeStatus * Show hours remaining when over 90 min * Update var naming * Clean * Update id to prevent conflicts * Automatically show and remove Banner based on start / end time * Refactor: AnnouncementBanner to use getCountdownTimeStatus * Automate Banners to appear / disappear after start / end time respectively * Keep in sync interval timers across all event countdown components * Add comments * Remove EthDencun * Hide Rebate in Bridge Card --------- Co-authored-by: aureliusbtc <82057759+aureliusbtc@users.noreply.github.com> Co-authored-by: χ² <88190723+ChiTimesChi@users.noreply.github.com> Co-authored-by: abtestingalpha <104046418+abtestingalpha@users.noreply.github.com> From e671f4d27f75c188d89705b0899096d752bcf85a Mon Sep 17 00:00:00 2001 From: bigboydiamonds <57741810+bigboydiamonds@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:35:49 -0700 Subject: [PATCH 10/29] Display m over min --- .../components/Maintenance/EventCountdownProgressBar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/synapse-interface/components/Maintenance/EventCountdownProgressBar.tsx b/packages/synapse-interface/components/Maintenance/EventCountdownProgressBar.tsx index c2e9a9c41a..dfd8f6c018 100644 --- a/packages/synapse-interface/components/Maintenance/EventCountdownProgressBar.tsx +++ b/packages/synapse-interface/components/Maintenance/EventCountdownProgressBar.tsx @@ -18,7 +18,7 @@ export const useEventCountdownProgressBar = ( const timeRemaining: string = totalTimeRemainingInMinutes > 90 ? `${hoursRemaining}h` - : `${totalTimeRemainingInMinutes}min` + : `${totalTimeRemainingInMinutes}m` let status: 'idle' | 'pending' | 'complete' From 2c41189eb4e02cf864857c287950d4adf912bae5 Mon Sep 17 00:00:00 2001 From: abtestingalpha <104046418+abtestingalpha@users.noreply.github.com> Date: Wed, 13 Mar 2024 21:57:31 -0500 Subject: [PATCH 11/29] Adds txn support url (#2286) --- packages/widget/src/components/TransactionSupport.tsx | 9 +++++---- packages/widget/src/constants/index.ts | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/widget/src/components/TransactionSupport.tsx b/packages/widget/src/components/TransactionSupport.tsx index a5c5d9a45a..b542a4a6b3 100644 --- a/packages/widget/src/components/TransactionSupport.tsx +++ b/packages/widget/src/components/TransactionSupport.tsx @@ -1,4 +1,5 @@ -// TODO: Add FAQ link +import { TRANSACTION_SUPPORT_URL } from '@/constants/index' + export const TransactionSupport = () => { return (
{ >
What's taking so long?
- {/* { > F.A.Q -
/
*/} +
/
Date: Thu, 14 Mar 2024 03:01:20 +0000 Subject: [PATCH 12/29] Publish - @synapsecns/synapse-interface@0.9.1 - @synapsecns/widget@0.1.4 --- packages/synapse-interface/CHANGELOG.md | 8 ++++++++ packages/synapse-interface/package.json | 2 +- packages/widget/CHANGELOG.md | 8 ++++++++ packages/widget/package.json | 2 +- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/synapse-interface/CHANGELOG.md b/packages/synapse-interface/CHANGELOG.md index b952fc4ed8..643130f376 100644 --- a/packages/synapse-interface/CHANGELOG.md +++ b/packages/synapse-interface/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.9.1](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.9.0...@synapsecns/synapse-interface@0.9.1) (2024-03-14) + +**Note:** Version bump only for package @synapsecns/synapse-interface + + + + + # [0.9.0](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.8.0...@synapsecns/synapse-interface@0.9.0) (2024-03-13) diff --git a/packages/synapse-interface/package.json b/packages/synapse-interface/package.json index 6c19f1856c..51e3a5295c 100644 --- a/packages/synapse-interface/package.json +++ b/packages/synapse-interface/package.json @@ -1,6 +1,6 @@ { "name": "@synapsecns/synapse-interface", - "version": "0.9.0", + "version": "0.9.1", "private": true, "engines": { "node": ">=16.0.0" diff --git a/packages/widget/CHANGELOG.md b/packages/widget/CHANGELOG.md index 3c031f81a7..806ce3fc98 100644 --- a/packages/widget/CHANGELOG.md +++ b/packages/widget/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.4](https://github.com/synapsecns/sanguine/compare/@synapsecns/widget@0.1.3...@synapsecns/widget@0.1.4) (2024-03-14) + +**Note:** Version bump only for package @synapsecns/widget + + + + + ## [0.1.3](https://github.com/synapsecns/sanguine/compare/@synapsecns/widget@0.1.2...@synapsecns/widget@0.1.3) (2024-03-13) **Note:** Version bump only for package @synapsecns/widget diff --git a/packages/widget/package.json b/packages/widget/package.json index 7a2ff9f859..8c2143362f 100644 --- a/packages/widget/package.json +++ b/packages/widget/package.json @@ -1,7 +1,7 @@ { "name": "@synapsecns/widget", "description": "Widget library for interacting with the Synapse Protocol", - "version": "0.1.3", + "version": "0.1.4", "license": "MIT", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", From 03682d9323d5c00d0bba2aa80d27118574eba386 Mon Sep 17 00:00:00 2001 From: trajan0x <83933037+trajan0x@users.noreply.github.com> Date: Thu, 14 Mar 2024 09:06:45 +0100 Subject: [PATCH 13/29] remove vercel analytics (#2273) Co-authored-by: Trajan0x --- packages/synapse-interface/package.json | 1 - packages/synapse-interface/pages/_app.tsx | 2 -- 2 files changed, 3 deletions(-) diff --git a/packages/synapse-interface/package.json b/packages/synapse-interface/package.json index 51e3a5295c..2f989d3cd9 100644 --- a/packages/synapse-interface/package.json +++ b/packages/synapse-interface/package.json @@ -51,7 +51,6 @@ "@types/react": "18.0.28", "@types/react-dom": "18.0.11", "@types/web3": "^1.2.2", - "@vercel/analytics": "^1.0.2", "@visx/chord": "^3.0.0", "@visx/shape": "^3.0.0", "@wagmi/core": "^1.4.12", diff --git a/packages/synapse-interface/pages/_app.tsx b/packages/synapse-interface/pages/_app.tsx index 32d8836c0e..6e544c16e2 100644 --- a/packages/synapse-interface/pages/_app.tsx +++ b/packages/synapse-interface/pages/_app.tsx @@ -3,7 +3,6 @@ import '@rainbow-me/rainbowkit/styles.css' import type { AppProps } from 'next/app' import Head from 'next/head' import '@/patch' -import { Analytics } from '@vercel/analytics/react' import { PersistGate } from 'redux-persist/integration/react' import LogRocket from 'logrocket' import setupLogRocketReact from 'logrocket-react' @@ -53,7 +52,6 @@ const App = ({ Component, pageProps }: AppProps) => { - From bd8ae5cfe49c15f670a6d088d7ff6eed6d57864e Mon Sep 17 00:00:00 2001 From: trajan0x Date: Thu, 14 Mar 2024 08:10:25 +0000 Subject: [PATCH 14/29] Publish - @synapsecns/synapse-interface@0.9.2 --- packages/synapse-interface/CHANGELOG.md | 8 ++++++++ packages/synapse-interface/package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/synapse-interface/CHANGELOG.md b/packages/synapse-interface/CHANGELOG.md index 643130f376..c71b5b3fa5 100644 --- a/packages/synapse-interface/CHANGELOG.md +++ b/packages/synapse-interface/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.9.2](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.9.1...@synapsecns/synapse-interface@0.9.2) (2024-03-14) + +**Note:** Version bump only for package @synapsecns/synapse-interface + + + + + ## [0.9.1](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.9.0...@synapsecns/synapse-interface@0.9.1) (2024-03-14) **Note:** Version bump only for package @synapsecns/synapse-interface diff --git a/packages/synapse-interface/package.json b/packages/synapse-interface/package.json index 2f989d3cd9..beb14c40d8 100644 --- a/packages/synapse-interface/package.json +++ b/packages/synapse-interface/package.json @@ -1,6 +1,6 @@ { "name": "@synapsecns/synapse-interface", - "version": "0.9.1", + "version": "0.9.2", "private": true, "engines": { "node": ">=16.0.0" From f51c33011fc75e9b27153d2ce153eebe738ce441 Mon Sep 17 00:00:00 2001 From: dwasse Date: Thu, 14 Mar 2024 03:14:44 -0500 Subject: [PATCH 15/29] Log RFQ relayer signer address upon startup (#2257) * Feat: log signer address * [goreleaser] * [goreleaser] * remove vercel analytics * func fix --------- Co-authored-by: aureliusbtc <82057759+aureliusbtc@users.noreply.github.com> Co-authored-by: Trajan0x --- services/rfq/relayer/service/relayer.go | 1 + 1 file changed, 1 insertion(+) diff --git a/services/rfq/relayer/service/relayer.go b/services/rfq/relayer/service/relayer.go index d1af5aa87a..104290e19c 100644 --- a/services/rfq/relayer/service/relayer.go +++ b/services/rfq/relayer/service/relayer.go @@ -93,6 +93,7 @@ func NewRelayer(ctx context.Context, metricHandler metrics.Handler, cfg relconfi if err != nil { return nil, fmt.Errorf("could not get signer: %w", err) } + fmt.Printf("loaded signer with address: %s\n", sg.Address().String()) sm := submitter.NewTransactionSubmitter(metricHandler, sg, omniClient, store.SubmitterDB(), &cfg.SubmitterConfig) From 3c7f133527548054e0fbd735fb1223b0f710c2cf Mon Sep 17 00:00:00 2001 From: trajan0x <83933037+trajan0x@users.noreply.github.com> Date: Thu, 14 Mar 2024 13:07:44 +0100 Subject: [PATCH 16/29] regen rfq (#2288) * regen rfq * fix compiler issue * relayerrole fix --------- Co-authored-by: Trajan0x --- services/rfq/api/client/suite_test.go | 5 +- services/rfq/api/rest/suite_test.go | 6 +- .../contracts/fastbridge/fastbridge.abigen.go | 9185 ++++++----- .../fastbridge/fastbridge.contractinfo.json | 2 +- .../fastbridgemock/fastbridgemock.abigen.go | 12595 +++++++--------- .../fastbridgemock.contractinfo.json | 2 +- services/rfq/e2e/setup_test.go | 5 +- services/rfq/relayer/relapi/suite_test.go | 6 +- 8 files changed, 9784 insertions(+), 12022 deletions(-) diff --git a/services/rfq/api/client/suite_test.go b/services/rfq/api/client/suite_test.go index 779098d974..faf9e6c35d 100644 --- a/services/rfq/api/client/suite_test.go +++ b/services/rfq/api/client/suite_test.go @@ -159,7 +159,10 @@ func (c *ClientSuite) SetupSuite() { fastBridgeInstance, err := fastbridge.NewFastBridge(fastBridgeAddress, backend) c.Require().NoError(err) - tx, err = fastBridgeInstance.AddRelayer(auth, c.testWallet.Address()) + relayerRole, err := fastBridgeInstance.RELAYERROLE(&bind.CallOpts{Context: c.GetTestContext()}) + c.NoError(err) + + tx, err = fastBridgeInstance.GrantRole(auth, relayerRole, c.testWallet.Address()) c.Require().NoError(err) backend.WaitForConfirmation(c.GetSuiteContext(), tx) diff --git a/services/rfq/api/rest/suite_test.go b/services/rfq/api/rest/suite_test.go index 903093b1fb..ebfbf344f7 100644 --- a/services/rfq/api/rest/suite_test.go +++ b/services/rfq/api/rest/suite_test.go @@ -154,8 +154,10 @@ func (c *ServerSuite) SetupSuite() { c.fastBridgeAddressMap.Store(chainID.Uint64(), fastBridgeAddress) fastBridgeInstance, err := fastbridge.NewFastBridge(fastBridgeAddress, backend) - c.Require().NoError(err) - tx, err = fastBridgeInstance.AddRelayer(auth, c.testWallet.Address()) + relayerRole, err := fastBridgeInstance.RELAYERROLE(&bind.CallOpts{Context: c.GetTestContext()}) + c.NoError(err) + + tx, err = fastBridgeInstance.GrantRole(auth, relayerRole, c.testWallet.Address()) c.Require().NoError(err) backend.WaitForConfirmation(c.GetSuiteContext(), tx) diff --git a/services/rfq/contracts/fastbridge/fastbridge.abigen.go b/services/rfq/contracts/fastbridge/fastbridge.abigen.go index f19ddca7c7..12663b4c35 100644 --- a/services/rfq/contracts/fastbridge/fastbridge.abigen.go +++ b/services/rfq/contracts/fastbridge/fastbridge.abigen.go @@ -895,135 +895,128 @@ func (_AccessControl *AccessControlFilterer) ParseRoleRevoked(log types.Log) (*A return event, nil } -// AddressMetaData contains all meta data concerning the Address contract. -var AddressMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"}]", - Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220d80dee42c3c64f0baf51820376f96b740ea0cfbed8a9b603c3bfbdaab286bbc964736f6c63430008140033", +// AccessControlEnumerableMetaData contains all meta data concerning the AccessControlEnumerable contract. +var AccessControlEnumerableMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "a217fddf": "DEFAULT_ADMIN_ROLE()", + "248a9ca3": "getRoleAdmin(bytes32)", + "9010d07c": "getRoleMember(bytes32,uint256)", + "ca15c873": "getRoleMemberCount(bytes32)", + "2f2ff15d": "grantRole(bytes32,address)", + "91d14854": "hasRole(bytes32,address)", + "36568abe": "renounceRole(bytes32,address)", + "d547741f": "revokeRole(bytes32,address)", + "01ffc9a7": "supportsInterface(bytes4)", + }, } -// AddressABI is the input ABI used to generate the binding from. -// Deprecated: Use AddressMetaData.ABI instead. -var AddressABI = AddressMetaData.ABI - -// AddressBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use AddressMetaData.Bin instead. -var AddressBin = AddressMetaData.Bin - -// DeployAddress deploys a new Ethereum contract, binding an instance of Address to it. -func DeployAddress(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Address, error) { - parsed, err := AddressMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } +// AccessControlEnumerableABI is the input ABI used to generate the binding from. +// Deprecated: Use AccessControlEnumerableMetaData.ABI instead. +var AccessControlEnumerableABI = AccessControlEnumerableMetaData.ABI - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(AddressBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Address{AddressCaller: AddressCaller{contract: contract}, AddressTransactor: AddressTransactor{contract: contract}, AddressFilterer: AddressFilterer{contract: contract}}, nil -} +// Deprecated: Use AccessControlEnumerableMetaData.Sigs instead. +// AccessControlEnumerableFuncSigs maps the 4-byte function signature to its string representation. +var AccessControlEnumerableFuncSigs = AccessControlEnumerableMetaData.Sigs -// Address is an auto generated Go binding around an Ethereum contract. -type Address struct { - AddressCaller // Read-only binding to the contract - AddressTransactor // Write-only binding to the contract - AddressFilterer // Log filterer for contract events +// AccessControlEnumerable is an auto generated Go binding around an Ethereum contract. +type AccessControlEnumerable struct { + AccessControlEnumerableCaller // Read-only binding to the contract + AccessControlEnumerableTransactor // Write-only binding to the contract + AccessControlEnumerableFilterer // Log filterer for contract events } -// AddressCaller is an auto generated read-only Go binding around an Ethereum contract. -type AddressCaller struct { +// AccessControlEnumerableCaller is an auto generated read-only Go binding around an Ethereum contract. +type AccessControlEnumerableCaller struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// AddressTransactor is an auto generated write-only Go binding around an Ethereum contract. -type AddressTransactor struct { +// AccessControlEnumerableTransactor is an auto generated write-only Go binding around an Ethereum contract. +type AccessControlEnumerableTransactor struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// AddressFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type AddressFilterer struct { +// AccessControlEnumerableFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type AccessControlEnumerableFilterer struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// AddressSession is an auto generated Go binding around an Ethereum contract, +// AccessControlEnumerableSession is an auto generated Go binding around an Ethereum contract, // with pre-set call and transact options. -type AddressSession struct { - Contract *Address // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +type AccessControlEnumerableSession struct { + Contract *AccessControlEnumerable // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// AddressCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// AccessControlEnumerableCallerSession is an auto generated read-only Go binding around an Ethereum contract, // with pre-set call options. -type AddressCallerSession struct { - Contract *AddressCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session +type AccessControlEnumerableCallerSession struct { + Contract *AccessControlEnumerableCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session } -// AddressTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// AccessControlEnumerableTransactorSession is an auto generated write-only Go binding around an Ethereum contract, // with pre-set transact options. -type AddressTransactorSession struct { - Contract *AddressTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +type AccessControlEnumerableTransactorSession struct { + Contract *AccessControlEnumerableTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// AddressRaw is an auto generated low-level Go binding around an Ethereum contract. -type AddressRaw struct { - Contract *Address // Generic contract binding to access the raw methods on +// AccessControlEnumerableRaw is an auto generated low-level Go binding around an Ethereum contract. +type AccessControlEnumerableRaw struct { + Contract *AccessControlEnumerable // Generic contract binding to access the raw methods on } -// AddressCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type AddressCallerRaw struct { - Contract *AddressCaller // Generic read-only contract binding to access the raw methods on +// AccessControlEnumerableCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type AccessControlEnumerableCallerRaw struct { + Contract *AccessControlEnumerableCaller // Generic read-only contract binding to access the raw methods on } -// AddressTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type AddressTransactorRaw struct { - Contract *AddressTransactor // Generic write-only contract binding to access the raw methods on +// AccessControlEnumerableTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type AccessControlEnumerableTransactorRaw struct { + Contract *AccessControlEnumerableTransactor // Generic write-only contract binding to access the raw methods on } -// NewAddress creates a new instance of Address, bound to a specific deployed contract. -func NewAddress(address common.Address, backend bind.ContractBackend) (*Address, error) { - contract, err := bindAddress(address, backend, backend, backend) +// NewAccessControlEnumerable creates a new instance of AccessControlEnumerable, bound to a specific deployed contract. +func NewAccessControlEnumerable(address common.Address, backend bind.ContractBackend) (*AccessControlEnumerable, error) { + contract, err := bindAccessControlEnumerable(address, backend, backend, backend) if err != nil { return nil, err } - return &Address{AddressCaller: AddressCaller{contract: contract}, AddressTransactor: AddressTransactor{contract: contract}, AddressFilterer: AddressFilterer{contract: contract}}, nil + return &AccessControlEnumerable{AccessControlEnumerableCaller: AccessControlEnumerableCaller{contract: contract}, AccessControlEnumerableTransactor: AccessControlEnumerableTransactor{contract: contract}, AccessControlEnumerableFilterer: AccessControlEnumerableFilterer{contract: contract}}, nil } -// NewAddressCaller creates a new read-only instance of Address, bound to a specific deployed contract. -func NewAddressCaller(address common.Address, caller bind.ContractCaller) (*AddressCaller, error) { - contract, err := bindAddress(address, caller, nil, nil) +// NewAccessControlEnumerableCaller creates a new read-only instance of AccessControlEnumerable, bound to a specific deployed contract. +func NewAccessControlEnumerableCaller(address common.Address, caller bind.ContractCaller) (*AccessControlEnumerableCaller, error) { + contract, err := bindAccessControlEnumerable(address, caller, nil, nil) if err != nil { return nil, err } - return &AddressCaller{contract: contract}, nil + return &AccessControlEnumerableCaller{contract: contract}, nil } -// NewAddressTransactor creates a new write-only instance of Address, bound to a specific deployed contract. -func NewAddressTransactor(address common.Address, transactor bind.ContractTransactor) (*AddressTransactor, error) { - contract, err := bindAddress(address, nil, transactor, nil) +// NewAccessControlEnumerableTransactor creates a new write-only instance of AccessControlEnumerable, bound to a specific deployed contract. +func NewAccessControlEnumerableTransactor(address common.Address, transactor bind.ContractTransactor) (*AccessControlEnumerableTransactor, error) { + contract, err := bindAccessControlEnumerable(address, nil, transactor, nil) if err != nil { return nil, err } - return &AddressTransactor{contract: contract}, nil + return &AccessControlEnumerableTransactor{contract: contract}, nil } -// NewAddressFilterer creates a new log filterer instance of Address, bound to a specific deployed contract. -func NewAddressFilterer(address common.Address, filterer bind.ContractFilterer) (*AddressFilterer, error) { - contract, err := bindAddress(address, nil, nil, filterer) +// NewAccessControlEnumerableFilterer creates a new log filterer instance of AccessControlEnumerable, bound to a specific deployed contract. +func NewAccessControlEnumerableFilterer(address common.Address, filterer bind.ContractFilterer) (*AccessControlEnumerableFilterer, error) { + contract, err := bindAccessControlEnumerable(address, nil, nil, filterer) if err != nil { return nil, err } - return &AddressFilterer{contract: contract}, nil + return &AccessControlEnumerableFilterer{contract: contract}, nil } -// bindAddress binds a generic wrapper to an already deployed contract. -func bindAddress(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := AddressMetaData.GetAbi() +// bindAccessControlEnumerable binds a generic wrapper to an already deployed contract. +func bindAccessControlEnumerable(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := AccessControlEnumerableMetaData.GetAbi() if err != nil { return nil, err } @@ -1034,870 +1027,616 @@ func bindAddress(address common.Address, caller bind.ContractCaller, transactor // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. -func (_Address *AddressRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Address.Contract.AddressCaller.contract.Call(opts, result, method, params...) +func (_AccessControlEnumerable *AccessControlEnumerableRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AccessControlEnumerable.Contract.AccessControlEnumerableCaller.contract.Call(opts, result, method, params...) } // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. -func (_Address *AddressRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Address.Contract.AddressTransactor.contract.Transfer(opts) +func (_AccessControlEnumerable *AccessControlEnumerableRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.AccessControlEnumerableTransactor.contract.Transfer(opts) } // Transact invokes the (paid) contract method with params as input values. -func (_Address *AddressRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Address.Contract.AddressTransactor.contract.Transact(opts, method, params...) +func (_AccessControlEnumerable *AccessControlEnumerableRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.AccessControlEnumerableTransactor.contract.Transact(opts, method, params...) } // Call invokes the (constant) contract method with params as input values and // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. -func (_Address *AddressCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Address.Contract.contract.Call(opts, result, method, params...) +func (_AccessControlEnumerable *AccessControlEnumerableCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AccessControlEnumerable.Contract.contract.Call(opts, result, method, params...) } // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. -func (_Address *AddressTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Address.Contract.contract.Transfer(opts) +func (_AccessControlEnumerable *AccessControlEnumerableTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.contract.Transfer(opts) } // Transact invokes the (paid) contract method with params as input values. -func (_Address *AddressTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Address.Contract.contract.Transact(opts, method, params...) -} - -// AdminMetaData contains all meta data concerning the Admin contract. -var AdminMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"addGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"addGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"addRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"removeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"removeGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"removeRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Sigs: map[string]string{ - "a217fddf": "DEFAULT_ADMIN_ROLE()", - "bf333f2c": "FEE_BPS()", - "0f5f6ed7": "FEE_RATE_MAX()", - "ccc57490": "GOVERNOR_ROLE()", - "03ed0ee5": "GUARD_ROLE()", - "926d7d7f": "RELAYER_ROLE()", - "3c4a25d0": "addGovernor(address)", - "6913a63c": "addGuard(address)", - "dd39f00d": "addRelayer(address)", - "e00a83e0": "chainGasAmount()", - "248a9ca3": "getRoleAdmin(bytes32)", - "2f2ff15d": "grantRole(bytes32,address)", - "91d14854": "hasRole(bytes32,address)", - "58f85880": "protocolFeeRate()", - "dcf844a7": "protocolFees(address)", - "eecdac88": "removeGovernor(address)", - "b6235016": "removeGuard(address)", - "60f0a5ac": "removeRelayer(address)", - "36568abe": "renounceRole(bytes32,address)", - "d547741f": "revokeRole(bytes32,address)", - "b250fe6b": "setChainGasAmount(uint256)", - "b13aa2d6": "setProtocolFeeRate(uint256)", - "01ffc9a7": "supportsInterface(bytes4)", - "06f333f2": "sweepProtocolFees(address,address)", - }, - Bin: "0x608060405234801561001057600080fd5b50604051620015cf380380620015cf833981016040819052610031916100ef565b61003c600082610043565b505061011f565b6000828152602081815260408083206001600160a01b038516845290915281205460ff166100e5576000838152602081815260408083206001600160a01b03861684529091529020805460ff1916600117905561009d3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016100e9565b5060005b92915050565b60006020828403121561010157600080fd5b81516001600160a01b038116811461011857600080fd5b9392505050565b6114a0806200012f6000396000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c8063926d7d7f116100e3578063ccc574901161008c578063dd39f00d11610066578063dd39f00d146103b3578063e00a83e0146103c6578063eecdac88146103cf57600080fd5b8063ccc5749014610359578063d547741f14610380578063dcf844a71461039357600080fd5b8063b250fe6b116100bd578063b250fe6b14610329578063b62350161461033c578063bf333f2c1461034f57600080fd5b8063926d7d7f146102e7578063a217fddf1461030e578063b13aa2d61461031657600080fd5b806336568abe1161014557806360f0a5ac1161011f57806360f0a5ac1461027d5780636913a63c1461029057806391d14854146102a357600080fd5b806336568abe1461024e5780633c4a25d01461026157806358f858801461027457600080fd5b80630f5f6ed7116101765780630f5f6ed71461020f578063248a9ca3146102185780632f2ff15d1461023b57600080fd5b806301ffc9a71461019d57806303ed0ee5146101c557806306f333f2146101fa575b600080fd5b6101b06101ab366004611324565b6103e2565b60405190151581526020015b60405180910390f35b6101ec7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b6040519081526020016101bc565b61020d61020836600461138f565b61047b565b005b6101ec61271081565b6101ec6102263660046113c2565b60009081526020819052604090206001015490565b61020d6102493660046113db565b6105da565b61020d61025c3660046113db565b610605565b61020d61026f3660046113fe565b610663565b6101ec60015481565b61020d61028b3660046113fe565b610716565b61020d61029e3660046113fe565b6107c2565b6101b06102b13660046113db565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6101ec7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b6101ec600081565b61020d6103243660046113c2565b61086e565b61020d6103373660046113c2565b6109b8565b61020d61034a3660046113fe565b610a8e565b6101ec620f424081565b6101ec7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b61020d61038e3660046113db565b610b3a565b6101ec6103a13660046113fe565b60026020526000908152604090205481565b61020d6103c13660046113fe565b610b5f565b6101ec60035481565b61020d6103dd3660046113fe565b610c0b565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061047557507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16610518576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600260205260408120549081900361054b57505050565b73ffffffffffffffffffffffffffffffffffffffff831660008181526002602052604081205561057c908383610cb7565b6040805173ffffffffffffffffffffffffffffffffffffffff8086168252841660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b5050565b6000828152602081905260409020600101546105f581610e0e565b6105ff8383610e1b565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610654576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61065e8282610f17565b505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661069e57600080fd5b6106c87f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5582610e1b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5906020015b60405180910390a150565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661075157600080fd5b61077b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc482610f17565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b9060200161070b565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166107fd57600080fd5b6108277f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d82610e1b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f599060200161070b565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16610906576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f720000000000000000604482015260640161050f565b612710811115610972576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d617800000000000000000000000000000000604482015260640161050f565b600180549082905560408051828152602081018490527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a15050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16610a50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f720000000000000000604482015260640161050f565b600380549082905560408051828152602081018490527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa91016109ac565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610ac957600080fd5b610af37f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d82610f17565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d0489060200161070b565b600082815260208190526040902060010154610b5581610e0e565b6105ff8383610f17565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610b9a57600080fd5b610bc47fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc482610e1b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c59060200161070b565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610c4657600080fd5b610c707f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5582610f17565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b9060200161070b565b3073ffffffffffffffffffffffffffffffffffffffff831603610cd957505050565b80600003610ce657505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff841601610ded5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610d7d576040519150601f19603f3d011682016040523d82523d6000602084013e610d82565b606091505b50509050806105ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c656400000000000000000000000000604482015260640161050f565b61065e73ffffffffffffffffffffffffffffffffffffffff84168383610fd2565b610e18813361105f565b50565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16610f0f5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610ead3390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610475565b506000610475565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff1615610f0f5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610475565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261065e9084906110e5565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166105d6576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024810183905260440161050f565b600061110773ffffffffffffffffffffffffffffffffffffffff84168361117b565b9050805160001415801561112c57508080602001905181019061112a9190611419565b155b1561065e576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161050f565b606061118983836000611190565b9392505050565b6060814710156111ce576040517fcd78605900000000000000000000000000000000000000000000000000000000815230600482015260240161050f565b6000808573ffffffffffffffffffffffffffffffffffffffff1684866040516111f7919061143b565b60006040518083038185875af1925050503d8060008114611234576040519150601f19603f3d011682016040523d82523d6000602084013e611239565b606091505b5091509150611249868383611253565b9695505050505050565b60608261126857611263826112e2565b611189565b815115801561128c575073ffffffffffffffffffffffffffffffffffffffff84163b155b156112db576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015260240161050f565b5080611189565b8051156112f25780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561133657600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461118957600080fd5b803573ffffffffffffffffffffffffffffffffffffffff8116811461138a57600080fd5b919050565b600080604083850312156113a257600080fd5b6113ab83611366565b91506113b960208401611366565b90509250929050565b6000602082840312156113d457600080fd5b5035919050565b600080604083850312156113ee57600080fd5b823591506113b960208401611366565b60006020828403121561141057600080fd5b61118982611366565b60006020828403121561142b57600080fd5b8151801515811461118957600080fd5b6000825160005b8181101561145c5760208186018101518583015201611442565b50600092019182525091905056fea26469706673582212208769ea4fe17774b3d4152ad2514855ae96d78c10038c08e4a939ce0997735be264736f6c63430008140033", +func (_AccessControlEnumerable *AccessControlEnumerableTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.contract.Transact(opts, method, params...) } -// AdminABI is the input ABI used to generate the binding from. -// Deprecated: Use AdminMetaData.ABI instead. -var AdminABI = AdminMetaData.ABI - -// Deprecated: Use AdminMetaData.Sigs instead. -// AdminFuncSigs maps the 4-byte function signature to its string representation. -var AdminFuncSigs = AdminMetaData.Sigs - -// AdminBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use AdminMetaData.Bin instead. -var AdminBin = AdminMetaData.Bin +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_AccessControlEnumerable *AccessControlEnumerableCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _AccessControlEnumerable.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") -// DeployAdmin deploys a new Ethereum contract, binding an instance of Admin to it. -func DeployAdmin(auth *bind.TransactOpts, backend bind.ContractBackend, _owner common.Address) (common.Address, *types.Transaction, *Admin, error) { - parsed, err := AdminMetaData.GetAbi() if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") + return *new([32]byte), err } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(AdminBin), backend, _owner) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Admin{AdminCaller: AdminCaller{contract: contract}, AdminTransactor: AdminTransactor{contract: contract}, AdminFilterer: AdminFilterer{contract: contract}}, nil -} + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) -// Admin is an auto generated Go binding around an Ethereum contract. -type Admin struct { - AdminCaller // Read-only binding to the contract - AdminTransactor // Write-only binding to the contract - AdminFilterer // Log filterer for contract events -} + return out0, err -// AdminCaller is an auto generated read-only Go binding around an Ethereum contract. -type AdminCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// AdminTransactor is an auto generated write-only Go binding around an Ethereum contract. -type AdminTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_AccessControlEnumerable *AccessControlEnumerableSession) DEFAULTADMINROLE() ([32]byte, error) { + return _AccessControlEnumerable.Contract.DEFAULTADMINROLE(&_AccessControlEnumerable.CallOpts) } -// AdminFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type AdminFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_AccessControlEnumerable *AccessControlEnumerableCallerSession) DEFAULTADMINROLE() ([32]byte, error) { + return _AccessControlEnumerable.Contract.DEFAULTADMINROLE(&_AccessControlEnumerable.CallOpts) } -// AdminSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type AdminSession struct { - Contract *Admin // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_AccessControlEnumerable *AccessControlEnumerableCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { + var out []interface{} + err := _AccessControlEnumerable.contract.Call(opts, &out, "getRoleAdmin", role) -// AdminCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type AdminCallerSession struct { - Contract *AdminCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} + if err != nil { + return *new([32]byte), err + } -// AdminTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type AdminTransactorSession struct { - Contract *AdminTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err -// AdminRaw is an auto generated low-level Go binding around an Ethereum contract. -type AdminRaw struct { - Contract *Admin // Generic contract binding to access the raw methods on } -// AdminCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type AdminCallerRaw struct { - Contract *AdminCaller // Generic read-only contract binding to access the raw methods on +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_AccessControlEnumerable *AccessControlEnumerableSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _AccessControlEnumerable.Contract.GetRoleAdmin(&_AccessControlEnumerable.CallOpts, role) } -// AdminTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type AdminTransactorRaw struct { - Contract *AdminTransactor // Generic write-only contract binding to access the raw methods on +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_AccessControlEnumerable *AccessControlEnumerableCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _AccessControlEnumerable.Contract.GetRoleAdmin(&_AccessControlEnumerable.CallOpts, role) } -// NewAdmin creates a new instance of Admin, bound to a specific deployed contract. -func NewAdmin(address common.Address, backend bind.ContractBackend) (*Admin, error) { - contract, err := bindAdmin(address, backend, backend, backend) +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. +// +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_AccessControlEnumerable *AccessControlEnumerableCaller) GetRoleMember(opts *bind.CallOpts, role [32]byte, index *big.Int) (common.Address, error) { + var out []interface{} + err := _AccessControlEnumerable.contract.Call(opts, &out, "getRoleMember", role, index) + if err != nil { - return nil, err + return *new(common.Address), err } - return &Admin{AdminCaller: AdminCaller{contract: contract}, AdminTransactor: AdminTransactor{contract: contract}, AdminFilterer: AdminFilterer{contract: contract}}, nil + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + } -// NewAdminCaller creates a new read-only instance of Admin, bound to a specific deployed contract. -func NewAdminCaller(address common.Address, caller bind.ContractCaller) (*AdminCaller, error) { - contract, err := bindAdmin(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &AdminCaller{contract: contract}, nil +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. +// +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_AccessControlEnumerable *AccessControlEnumerableSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _AccessControlEnumerable.Contract.GetRoleMember(&_AccessControlEnumerable.CallOpts, role, index) } -// NewAdminTransactor creates a new write-only instance of Admin, bound to a specific deployed contract. -func NewAdminTransactor(address common.Address, transactor bind.ContractTransactor) (*AdminTransactor, error) { - contract, err := bindAdmin(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &AdminTransactor{contract: contract}, nil +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. +// +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_AccessControlEnumerable *AccessControlEnumerableCallerSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _AccessControlEnumerable.Contract.GetRoleMember(&_AccessControlEnumerable.CallOpts, role, index) } -// NewAdminFilterer creates a new log filterer instance of Admin, bound to a specific deployed contract. -func NewAdminFilterer(address common.Address, filterer bind.ContractFilterer) (*AdminFilterer, error) { - contract, err := bindAdmin(address, nil, nil, filterer) +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. +// +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_AccessControlEnumerable *AccessControlEnumerableCaller) GetRoleMemberCount(opts *bind.CallOpts, role [32]byte) (*big.Int, error) { + var out []interface{} + err := _AccessControlEnumerable.contract.Call(opts, &out, "getRoleMemberCount", role) + if err != nil { - return nil, err + return *new(*big.Int), err } - return &AdminFilterer{contract: contract}, nil -} - -// bindAdmin binds a generic wrapper to an already deployed contract. -func bindAdmin(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := AdminMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Admin *AdminRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Admin.Contract.AdminCaller.contract.Call(opts, result, method, params...) -} -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Admin *AdminRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Admin.Contract.AdminTransactor.contract.Transfer(opts) -} + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) -// Transact invokes the (paid) contract method with params as input values. -func (_Admin *AdminRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Admin.Contract.AdminTransactor.contract.Transact(opts, method, params...) -} + return out0, err -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Admin *AdminCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Admin.Contract.contract.Call(opts, result, method, params...) } -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Admin *AdminTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Admin.Contract.contract.Transfer(opts) +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. +// +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_AccessControlEnumerable *AccessControlEnumerableSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _AccessControlEnumerable.Contract.GetRoleMemberCount(&_AccessControlEnumerable.CallOpts, role) } -// Transact invokes the (paid) contract method with params as input values. -func (_Admin *AdminTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Admin.Contract.contract.Transact(opts, method, params...) +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. +// +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_AccessControlEnumerable *AccessControlEnumerableCallerSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _AccessControlEnumerable.Contract.GetRoleMemberCount(&_AccessControlEnumerable.CallOpts, role) } -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// HasRole is a free data retrieval call binding the contract method 0x91d14854. // -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_Admin *AdminCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_AccessControlEnumerable *AccessControlEnumerableCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { var out []interface{} - err := _Admin.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") + err := _AccessControlEnumerable.contract.Call(opts, &out, "hasRole", role, account) if err != nil { - return *new([32]byte), err + return *new(bool), err } - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) return out0, err } -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// HasRole is a free data retrieval call binding the contract method 0x91d14854. // -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_Admin *AdminSession) DEFAULTADMINROLE() ([32]byte, error) { - return _Admin.Contract.DEFAULTADMINROLE(&_Admin.CallOpts) +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_AccessControlEnumerable *AccessControlEnumerableSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _AccessControlEnumerable.Contract.HasRole(&_AccessControlEnumerable.CallOpts, role, account) } -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// HasRole is a free data retrieval call binding the contract method 0x91d14854. // -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_Admin *AdminCallerSession) DEFAULTADMINROLE() ([32]byte, error) { - return _Admin.Contract.DEFAULTADMINROLE(&_Admin.CallOpts) +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_AccessControlEnumerable *AccessControlEnumerableCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _AccessControlEnumerable.Contract.HasRole(&_AccessControlEnumerable.CallOpts, role, account) } -// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: function FEE_BPS() view returns(uint256) -func (_Admin *AdminCaller) FEEBPS(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_AccessControlEnumerable *AccessControlEnumerableCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { var out []interface{} - err := _Admin.contract.Call(opts, &out, "FEE_BPS") + err := _AccessControlEnumerable.contract.Call(opts, &out, "supportsInterface", interfaceId) if err != nil { - return *new(*big.Int), err + return *new(bool), err } - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) return out0, err } -// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: function FEE_BPS() view returns(uint256) -func (_Admin *AdminSession) FEEBPS() (*big.Int, error) { - return _Admin.Contract.FEEBPS(&_Admin.CallOpts) +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_AccessControlEnumerable *AccessControlEnumerableSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _AccessControlEnumerable.Contract.SupportsInterface(&_AccessControlEnumerable.CallOpts, interfaceId) } -// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: function FEE_BPS() view returns(uint256) -func (_Admin *AdminCallerSession) FEEBPS() (*big.Int, error) { - return _Admin.Contract.FEEBPS(&_Admin.CallOpts) +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_AccessControlEnumerable *AccessControlEnumerableCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _AccessControlEnumerable.Contract.SupportsInterface(&_AccessControlEnumerable.CallOpts, interfaceId) } -// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. // -// Solidity: function FEE_RATE_MAX() view returns(uint256) -func (_Admin *AdminCaller) FEERATEMAX(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "FEE_RATE_MAX") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_AccessControlEnumerable *AccessControlEnumerableTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _AccessControlEnumerable.contract.Transact(opts, "grantRole", role, account) } -// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. // -// Solidity: function FEE_RATE_MAX() view returns(uint256) -func (_Admin *AdminSession) FEERATEMAX() (*big.Int, error) { - return _Admin.Contract.FEERATEMAX(&_Admin.CallOpts) +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_AccessControlEnumerable *AccessControlEnumerableSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.GrantRole(&_AccessControlEnumerable.TransactOpts, role, account) } -// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. // -// Solidity: function FEE_RATE_MAX() view returns(uint256) -func (_Admin *AdminCallerSession) FEERATEMAX() (*big.Int, error) { - return _Admin.Contract.FEERATEMAX(&_Admin.CallOpts) +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_AccessControlEnumerable *AccessControlEnumerableTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.GrantRole(&_AccessControlEnumerable.TransactOpts, role, account) } -// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. // -// Solidity: function GOVERNOR_ROLE() view returns(bytes32) -func (_Admin *AdminCaller) GOVERNORROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "GOVERNOR_ROLE") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_AccessControlEnumerable *AccessControlEnumerableTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _AccessControlEnumerable.contract.Transact(opts, "renounceRole", role, callerConfirmation) } -// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. // -// Solidity: function GOVERNOR_ROLE() view returns(bytes32) -func (_Admin *AdminSession) GOVERNORROLE() ([32]byte, error) { - return _Admin.Contract.GOVERNORROLE(&_Admin.CallOpts) +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_AccessControlEnumerable *AccessControlEnumerableSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.RenounceRole(&_AccessControlEnumerable.TransactOpts, role, callerConfirmation) } -// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. // -// Solidity: function GOVERNOR_ROLE() view returns(bytes32) -func (_Admin *AdminCallerSession) GOVERNORROLE() ([32]byte, error) { - return _Admin.Contract.GOVERNORROLE(&_Admin.CallOpts) +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_AccessControlEnumerable *AccessControlEnumerableTransactorSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.RenounceRole(&_AccessControlEnumerable.TransactOpts, role, callerConfirmation) } -// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. // -// Solidity: function GUARD_ROLE() view returns(bytes32) -func (_Admin *AdminCaller) GUARDROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "GUARD_ROLE") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_AccessControlEnumerable *AccessControlEnumerableTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _AccessControlEnumerable.contract.Transact(opts, "revokeRole", role, account) } -// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. // -// Solidity: function GUARD_ROLE() view returns(bytes32) -func (_Admin *AdminSession) GUARDROLE() ([32]byte, error) { - return _Admin.Contract.GUARDROLE(&_Admin.CallOpts) +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_AccessControlEnumerable *AccessControlEnumerableSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.RevokeRole(&_AccessControlEnumerable.TransactOpts, role, account) } -// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. // -// Solidity: function GUARD_ROLE() view returns(bytes32) -func (_Admin *AdminCallerSession) GUARDROLE() ([32]byte, error) { - return _Admin.Contract.GUARDROLE(&_Admin.CallOpts) +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_AccessControlEnumerable *AccessControlEnumerableTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.RevokeRole(&_AccessControlEnumerable.TransactOpts, role, account) } -// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. -// -// Solidity: function RELAYER_ROLE() view returns(bytes32) -func (_Admin *AdminCaller) RELAYERROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "RELAYER_ROLE") +// AccessControlEnumerableRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the AccessControlEnumerable contract. +type AccessControlEnumerableRoleAdminChangedIterator struct { + Event *AccessControlEnumerableRoleAdminChanged // Event containing the contract specifics and raw log - if err != nil { - return *new([32]byte), err + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AccessControlEnumerableRoleAdminChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(AccessControlEnumerableRoleAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(AccessControlEnumerableRoleAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true - return out0, err + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} +// Error returns any retrieval or parsing error occurred during filtering. +func (it *AccessControlEnumerableRoleAdminChangedIterator) Error() error { + return it.fail } -// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. -// -// Solidity: function RELAYER_ROLE() view returns(bytes32) -func (_Admin *AdminSession) RELAYERROLE() ([32]byte, error) { - return _Admin.Contract.RELAYERROLE(&_Admin.CallOpts) +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AccessControlEnumerableRoleAdminChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil } -// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. -// -// Solidity: function RELAYER_ROLE() view returns(bytes32) -func (_Admin *AdminCallerSession) RELAYERROLE() ([32]byte, error) { - return _Admin.Contract.RELAYERROLE(&_Admin.CallOpts) +// AccessControlEnumerableRoleAdminChanged represents a RoleAdminChanged event raised by the AccessControlEnumerable contract. +type AccessControlEnumerableRoleAdminChanged struct { + Role [32]byte + PreviousAdminRole [32]byte + NewAdminRole [32]byte + Raw types.Log // Blockchain specific contextual infos } -// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. +// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. // -// Solidity: function chainGasAmount() view returns(uint256) -func (_Admin *AdminCaller) ChainGasAmount(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "chainGasAmount") +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_AccessControlEnumerable *AccessControlEnumerableFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*AccessControlEnumerableRoleAdminChangedIterator, error) { - if err != nil { - return *new(*big.Int), err + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) } - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. -// -// Solidity: function chainGasAmount() view returns(uint256) -func (_Admin *AdminSession) ChainGasAmount() (*big.Int, error) { - return _Admin.Contract.ChainGasAmount(&_Admin.CallOpts) + logs, sub, err := _AccessControlEnumerable.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) + if err != nil { + return nil, err + } + return &AccessControlEnumerableRoleAdminChangedIterator{contract: _AccessControlEnumerable.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil } -// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. +// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. // -// Solidity: function chainGasAmount() view returns(uint256) -func (_Admin *AdminCallerSession) ChainGasAmount() (*big.Int, error) { - return _Admin.Contract.ChainGasAmount(&_Admin.CallOpts) -} +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_AccessControlEnumerable *AccessControlEnumerableFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *AccessControlEnumerableRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_Admin *AdminCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "getRoleAdmin", role) + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + } + logs, sub, err := _AccessControlEnumerable.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { - return *new([32]byte), err + return nil, err } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(AccessControlEnumerableRoleAdminChanged) + if err := _AccessControlEnumerable.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { + return err + } + event.Raw = log - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil } -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. // -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_Admin *AdminSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { - return _Admin.Contract.GetRoleAdmin(&_Admin.CallOpts, role) +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_AccessControlEnumerable *AccessControlEnumerableFilterer) ParseRoleAdminChanged(log types.Log) (*AccessControlEnumerableRoleAdminChanged, error) { + event := new(AccessControlEnumerableRoleAdminChanged) + if err := _AccessControlEnumerable.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil } -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_Admin *AdminCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { - return _Admin.Contract.GetRoleAdmin(&_Admin.CallOpts, role) -} +// AccessControlEnumerableRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the AccessControlEnumerable contract. +type AccessControlEnumerableRoleGrantedIterator struct { + Event *AccessControlEnumerableRoleGranted // Event containing the contract specifics and raw log -// HasRole is a free data retrieval call binding the contract method 0x91d14854. -// -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_Admin *AdminCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "hasRole", role, account) + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data - if err != nil { - return *new(bool), err + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AccessControlEnumerableRoleGrantedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(AccessControlEnumerableRoleGranted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(AccessControlEnumerableRoleGranted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true - return out0, err + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} +// Error returns any retrieval or parsing error occurred during filtering. +func (it *AccessControlEnumerableRoleGrantedIterator) Error() error { + return it.fail } -// HasRole is a free data retrieval call binding the contract method 0x91d14854. -// -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_Admin *AdminSession) HasRole(role [32]byte, account common.Address) (bool, error) { - return _Admin.Contract.HasRole(&_Admin.CallOpts, role, account) +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AccessControlEnumerableRoleGrantedIterator) Close() error { + it.sub.Unsubscribe() + return nil } -// HasRole is a free data retrieval call binding the contract method 0x91d14854. -// -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_Admin *AdminCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { - return _Admin.Contract.HasRole(&_Admin.CallOpts, role, account) +// AccessControlEnumerableRoleGranted represents a RoleGranted event raised by the AccessControlEnumerable contract. +type AccessControlEnumerableRoleGranted struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos } -// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. // -// Solidity: function protocolFeeRate() view returns(uint256) -func (_Admin *AdminCaller) ProtocolFeeRate(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "protocolFeeRate") +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_AccessControlEnumerable *AccessControlEnumerableFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*AccessControlEnumerableRoleGrantedIterator, error) { - if err != nil { - return *new(*big.Int), err + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) } - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. -// -// Solidity: function protocolFeeRate() view returns(uint256) -func (_Admin *AdminSession) ProtocolFeeRate() (*big.Int, error) { - return _Admin.Contract.ProtocolFeeRate(&_Admin.CallOpts) + logs, sub, err := _AccessControlEnumerable.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return &AccessControlEnumerableRoleGrantedIterator{contract: _AccessControlEnumerable.contract, event: "RoleGranted", logs: logs, sub: sub}, nil } -// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. // -// Solidity: function protocolFeeRate() view returns(uint256) -func (_Admin *AdminCallerSession) ProtocolFeeRate() (*big.Int, error) { - return _Admin.Contract.ProtocolFeeRate(&_Admin.CallOpts) -} +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_AccessControlEnumerable *AccessControlEnumerableFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *AccessControlEnumerableRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { -// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. -// -// Solidity: function protocolFees(address ) view returns(uint256) -func (_Admin *AdminCaller) ProtocolFees(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "protocolFees", arg0) + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + logs, sub, err := _AccessControlEnumerable.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) if err != nil { - return *new(*big.Int), err + return nil, err } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(AccessControlEnumerableRoleGranted) + if err := _AccessControlEnumerable.contract.UnpackLog(event, "RoleGranted", log); err != nil { + return err + } + event.Raw = log - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil } -// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. -// -// Solidity: function protocolFees(address ) view returns(uint256) -func (_Admin *AdminSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { - return _Admin.Contract.ProtocolFees(&_Admin.CallOpts, arg0) -} - -// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. -// -// Solidity: function protocolFees(address ) view returns(uint256) -func (_Admin *AdminCallerSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { - return _Admin.Contract.ProtocolFees(&_Admin.CallOpts, arg0) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. // -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_Admin *AdminCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "supportsInterface", interfaceId) - - if err != nil { - return *new(bool), err +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_AccessControlEnumerable *AccessControlEnumerableFilterer) ParseRoleGranted(log types.Log) (*AccessControlEnumerableRoleGranted, error) { + event := new(AccessControlEnumerableRoleGranted) + if err := _AccessControlEnumerable.contract.UnpackLog(event, "RoleGranted", log); err != nil { + return nil, err } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_Admin *AdminSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _Admin.Contract.SupportsInterface(&_Admin.CallOpts, interfaceId) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_Admin *AdminCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _Admin.Contract.SupportsInterface(&_Admin.CallOpts, interfaceId) -} - -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. -// -// Solidity: function addGovernor(address _governor) returns() -func (_Admin *AdminTransactor) AddGovernor(opts *bind.TransactOpts, _governor common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "addGovernor", _governor) -} - -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. -// -// Solidity: function addGovernor(address _governor) returns() -func (_Admin *AdminSession) AddGovernor(_governor common.Address) (*types.Transaction, error) { - return _Admin.Contract.AddGovernor(&_Admin.TransactOpts, _governor) -} - -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. -// -// Solidity: function addGovernor(address _governor) returns() -func (_Admin *AdminTransactorSession) AddGovernor(_governor common.Address) (*types.Transaction, error) { - return _Admin.Contract.AddGovernor(&_Admin.TransactOpts, _governor) -} - -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. -// -// Solidity: function addGuard(address _guard) returns() -func (_Admin *AdminTransactor) AddGuard(opts *bind.TransactOpts, _guard common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "addGuard", _guard) -} - -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. -// -// Solidity: function addGuard(address _guard) returns() -func (_Admin *AdminSession) AddGuard(_guard common.Address) (*types.Transaction, error) { - return _Admin.Contract.AddGuard(&_Admin.TransactOpts, _guard) -} - -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. -// -// Solidity: function addGuard(address _guard) returns() -func (_Admin *AdminTransactorSession) AddGuard(_guard common.Address) (*types.Transaction, error) { - return _Admin.Contract.AddGuard(&_Admin.TransactOpts, _guard) -} - -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. -// -// Solidity: function addRelayer(address _relayer) returns() -func (_Admin *AdminTransactor) AddRelayer(opts *bind.TransactOpts, _relayer common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "addRelayer", _relayer) -} - -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. -// -// Solidity: function addRelayer(address _relayer) returns() -func (_Admin *AdminSession) AddRelayer(_relayer common.Address) (*types.Transaction, error) { - return _Admin.Contract.AddRelayer(&_Admin.TransactOpts, _relayer) -} - -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. -// -// Solidity: function addRelayer(address _relayer) returns() -func (_Admin *AdminTransactorSession) AddRelayer(_relayer common.Address) (*types.Transaction, error) { - return _Admin.Contract.AddRelayer(&_Admin.TransactOpts, _relayer) -} - -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. -// -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_Admin *AdminTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "grantRole", role, account) -} - -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. -// -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_Admin *AdminSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _Admin.Contract.GrantRole(&_Admin.TransactOpts, role, account) -} - -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. -// -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_Admin *AdminTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _Admin.Contract.GrantRole(&_Admin.TransactOpts, role, account) -} - -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. -// -// Solidity: function removeGovernor(address _governor) returns() -func (_Admin *AdminTransactor) RemoveGovernor(opts *bind.TransactOpts, _governor common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "removeGovernor", _governor) -} - -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. -// -// Solidity: function removeGovernor(address _governor) returns() -func (_Admin *AdminSession) RemoveGovernor(_governor common.Address) (*types.Transaction, error) { - return _Admin.Contract.RemoveGovernor(&_Admin.TransactOpts, _governor) -} - -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. -// -// Solidity: function removeGovernor(address _governor) returns() -func (_Admin *AdminTransactorSession) RemoveGovernor(_governor common.Address) (*types.Transaction, error) { - return _Admin.Contract.RemoveGovernor(&_Admin.TransactOpts, _governor) -} - -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. -// -// Solidity: function removeGuard(address _guard) returns() -func (_Admin *AdminTransactor) RemoveGuard(opts *bind.TransactOpts, _guard common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "removeGuard", _guard) -} - -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. -// -// Solidity: function removeGuard(address _guard) returns() -func (_Admin *AdminSession) RemoveGuard(_guard common.Address) (*types.Transaction, error) { - return _Admin.Contract.RemoveGuard(&_Admin.TransactOpts, _guard) -} - -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. -// -// Solidity: function removeGuard(address _guard) returns() -func (_Admin *AdminTransactorSession) RemoveGuard(_guard common.Address) (*types.Transaction, error) { - return _Admin.Contract.RemoveGuard(&_Admin.TransactOpts, _guard) -} - -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. -// -// Solidity: function removeRelayer(address _relayer) returns() -func (_Admin *AdminTransactor) RemoveRelayer(opts *bind.TransactOpts, _relayer common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "removeRelayer", _relayer) -} - -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. -// -// Solidity: function removeRelayer(address _relayer) returns() -func (_Admin *AdminSession) RemoveRelayer(_relayer common.Address) (*types.Transaction, error) { - return _Admin.Contract.RemoveRelayer(&_Admin.TransactOpts, _relayer) -} - -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. -// -// Solidity: function removeRelayer(address _relayer) returns() -func (_Admin *AdminTransactorSession) RemoveRelayer(_relayer common.Address) (*types.Transaction, error) { - return _Admin.Contract.RemoveRelayer(&_Admin.TransactOpts, _relayer) -} - -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. -// -// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() -func (_Admin *AdminTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "renounceRole", role, callerConfirmation) -} - -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. -// -// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() -func (_Admin *AdminSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { - return _Admin.Contract.RenounceRole(&_Admin.TransactOpts, role, callerConfirmation) -} - -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. -// -// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() -func (_Admin *AdminTransactorSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { - return _Admin.Contract.RenounceRole(&_Admin.TransactOpts, role, callerConfirmation) -} - -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. -// -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_Admin *AdminTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "revokeRole", role, account) -} - -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. -// -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_Admin *AdminSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _Admin.Contract.RevokeRole(&_Admin.TransactOpts, role, account) -} - -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. -// -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_Admin *AdminTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _Admin.Contract.RevokeRole(&_Admin.TransactOpts, role, account) -} - -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. -// -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_Admin *AdminTransactor) SetChainGasAmount(opts *bind.TransactOpts, newChainGasAmount *big.Int) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "setChainGasAmount", newChainGasAmount) -} - -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. -// -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_Admin *AdminSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { - return _Admin.Contract.SetChainGasAmount(&_Admin.TransactOpts, newChainGasAmount) -} - -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. -// -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_Admin *AdminTransactorSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { - return _Admin.Contract.SetChainGasAmount(&_Admin.TransactOpts, newChainGasAmount) -} - -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. -// -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_Admin *AdminTransactor) SetProtocolFeeRate(opts *bind.TransactOpts, newFeeRate *big.Int) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "setProtocolFeeRate", newFeeRate) -} - -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. -// -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_Admin *AdminSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { - return _Admin.Contract.SetProtocolFeeRate(&_Admin.TransactOpts, newFeeRate) -} - -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. -// -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_Admin *AdminTransactorSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { - return _Admin.Contract.SetProtocolFeeRate(&_Admin.TransactOpts, newFeeRate) -} - -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. -// -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_Admin *AdminTransactor) SweepProtocolFees(opts *bind.TransactOpts, token common.Address, recipient common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "sweepProtocolFees", token, recipient) -} - -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. -// -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_Admin *AdminSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { - return _Admin.Contract.SweepProtocolFees(&_Admin.TransactOpts, token, recipient) -} - -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. -// -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_Admin *AdminTransactorSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { - return _Admin.Contract.SweepProtocolFees(&_Admin.TransactOpts, token, recipient) + event.Raw = log + return event, nil } -// AdminChainGasAmountUpdatedIterator is returned from FilterChainGasAmountUpdated and is used to iterate over the raw logs and unpacked data for ChainGasAmountUpdated events raised by the Admin contract. -type AdminChainGasAmountUpdatedIterator struct { - Event *AdminChainGasAmountUpdated // Event containing the contract specifics and raw log +// AccessControlEnumerableRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the AccessControlEnumerable contract. +type AccessControlEnumerableRoleRevokedIterator struct { + Event *AccessControlEnumerableRoleRevoked // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -1911,7 +1650,7 @@ type AdminChainGasAmountUpdatedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *AdminChainGasAmountUpdatedIterator) Next() bool { +func (it *AccessControlEnumerableRoleRevokedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -1920,7 +1659,7 @@ func (it *AdminChainGasAmountUpdatedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(AdminChainGasAmountUpdated) + it.Event = new(AccessControlEnumerableRoleRevoked) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1935,7 +1674,7 @@ func (it *AdminChainGasAmountUpdatedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(AdminChainGasAmountUpdated) + it.Event = new(AccessControlEnumerableRoleRevoked) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1951,42 +1690,69 @@ func (it *AdminChainGasAmountUpdatedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminChainGasAmountUpdatedIterator) Error() error { +func (it *AccessControlEnumerableRoleRevokedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *AdminChainGasAmountUpdatedIterator) Close() error { +func (it *AccessControlEnumerableRoleRevokedIterator) Close() error { it.sub.Unsubscribe() return nil } -// AdminChainGasAmountUpdated represents a ChainGasAmountUpdated event raised by the Admin contract. -type AdminChainGasAmountUpdated struct { - OldChainGasAmount *big.Int - NewChainGasAmount *big.Int - Raw types.Log // Blockchain specific contextual infos +// AccessControlEnumerableRoleRevoked represents a RoleRevoked event raised by the AccessControlEnumerable contract. +type AccessControlEnumerableRoleRevoked struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos } -// FilterChainGasAmountUpdated is a free log retrieval operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. +// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_Admin *AdminFilterer) FilterChainGasAmountUpdated(opts *bind.FilterOpts) (*AdminChainGasAmountUpdatedIterator, error) { +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_AccessControlEnumerable *AccessControlEnumerableFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*AccessControlEnumerableRoleRevokedIterator, error) { - logs, sub, err := _Admin.contract.FilterLogs(opts, "ChainGasAmountUpdated") - if err != nil { - return nil, err + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) } - return &AdminChainGasAmountUpdatedIterator{contract: _Admin.contract, event: "ChainGasAmountUpdated", logs: logs, sub: sub}, nil -} -// WatchChainGasAmountUpdated is a free log subscription operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. + logs, sub, err := _AccessControlEnumerable.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return &AccessControlEnumerableRoleRevokedIterator{contract: _AccessControlEnumerable.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil +} + +// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_Admin *AdminFilterer) WatchChainGasAmountUpdated(opts *bind.WatchOpts, sink chan<- *AdminChainGasAmountUpdated) (event.Subscription, error) { +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_AccessControlEnumerable *AccessControlEnumerableFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *AccessControlEnumerableRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { - logs, sub, err := _Admin.contract.WatchLogs(opts, "ChainGasAmountUpdated") + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _AccessControlEnumerable.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) if err != nil { return nil, err } @@ -1996,8 +1762,8 @@ func (_Admin *AdminFilterer) WatchChainGasAmountUpdated(opts *bind.WatchOpts, si select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(AdminChainGasAmountUpdated) - if err := _Admin.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { + event := new(AccessControlEnumerableRoleRevoked) + if err := _AccessControlEnumerable.contract.UnpackLog(event, "RoleRevoked", log); err != nil { return err } event.Raw = log @@ -2018,1420 +1784,985 @@ func (_Admin *AdminFilterer) WatchChainGasAmountUpdated(opts *bind.WatchOpts, si }), nil } -// ParseChainGasAmountUpdated is a log parse operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. +// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_Admin *AdminFilterer) ParseChainGasAmountUpdated(log types.Log) (*AdminChainGasAmountUpdated, error) { - event := new(AdminChainGasAmountUpdated) - if err := _Admin.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_AccessControlEnumerable *AccessControlEnumerableFilterer) ParseRoleRevoked(log types.Log) (*AccessControlEnumerableRoleRevoked, error) { + event := new(AccessControlEnumerableRoleRevoked) + if err := _AccessControlEnumerable.contract.UnpackLog(event, "RoleRevoked", log); err != nil { return nil, err } event.Raw = log return event, nil } -// AdminFeeRateUpdatedIterator is returned from FilterFeeRateUpdated and is used to iterate over the raw logs and unpacked data for FeeRateUpdated events raised by the Admin contract. -type AdminFeeRateUpdatedIterator struct { - Event *AdminFeeRateUpdated // Event containing the contract specifics and raw log +// AddressMetaData contains all meta data concerning the Address contract. +var AddressMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"}]", + Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220484b80cd78ad146ed37d87f73b71fece9b7aef1b9090eddf52e592358acac67e64736f6c63430008140033", +} - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data +// AddressABI is the input ABI used to generate the binding from. +// Deprecated: Use AddressMetaData.ABI instead. +var AddressABI = AddressMetaData.ABI - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} +// AddressBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use AddressMetaData.Bin instead. +var AddressBin = AddressMetaData.Bin -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminFeeRateUpdatedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false +// DeployAddress deploys a new Ethereum contract, binding an instance of Address to it. +func DeployAddress(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Address, error) { + parsed, err := AddressMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminFeeRateUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminFeeRateUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(AddressBin), backend) + if err != nil { + return common.Address{}, nil, nil, err } + return address, tx, &Address{AddressCaller: AddressCaller{contract: contract}, AddressTransactor: AddressTransactor{contract: contract}, AddressFilterer: AddressFilterer{contract: contract}}, nil } -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminFeeRateUpdatedIterator) Error() error { - return it.fail +// Address is an auto generated Go binding around an Ethereum contract. +type Address struct { + AddressCaller // Read-only binding to the contract + AddressTransactor // Write-only binding to the contract + AddressFilterer // Log filterer for contract events } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminFeeRateUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// AddressCaller is an auto generated read-only Go binding around an Ethereum contract. +type AddressCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// AdminFeeRateUpdated represents a FeeRateUpdated event raised by the Admin contract. -type AdminFeeRateUpdated struct { - OldFeeRate *big.Int - NewFeeRate *big.Int - Raw types.Log // Blockchain specific contextual infos +// AddressTransactor is an auto generated write-only Go binding around an Ethereum contract. +type AddressTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// FilterFeeRateUpdated is a free log retrieval operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. -// -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_Admin *AdminFilterer) FilterFeeRateUpdated(opts *bind.FilterOpts) (*AdminFeeRateUpdatedIterator, error) { +// AddressFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type AddressFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} - logs, sub, err := _Admin.contract.FilterLogs(opts, "FeeRateUpdated") +// AddressSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type AddressSession struct { + Contract *Address // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// AddressCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type AddressCallerSession struct { + Contract *AddressCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// AddressTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type AddressTransactorSession struct { + Contract *AddressTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// AddressRaw is an auto generated low-level Go binding around an Ethereum contract. +type AddressRaw struct { + Contract *Address // Generic contract binding to access the raw methods on +} + +// AddressCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type AddressCallerRaw struct { + Contract *AddressCaller // Generic read-only contract binding to access the raw methods on +} + +// AddressTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type AddressTransactorRaw struct { + Contract *AddressTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewAddress creates a new instance of Address, bound to a specific deployed contract. +func NewAddress(address common.Address, backend bind.ContractBackend) (*Address, error) { + contract, err := bindAddress(address, backend, backend, backend) if err != nil { return nil, err } - return &AdminFeeRateUpdatedIterator{contract: _Admin.contract, event: "FeeRateUpdated", logs: logs, sub: sub}, nil + return &Address{AddressCaller: AddressCaller{contract: contract}, AddressTransactor: AddressTransactor{contract: contract}, AddressFilterer: AddressFilterer{contract: contract}}, nil } -// WatchFeeRateUpdated is a free log subscription operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. -// -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_Admin *AdminFilterer) WatchFeeRateUpdated(opts *bind.WatchOpts, sink chan<- *AdminFeeRateUpdated) (event.Subscription, error) { +// NewAddressCaller creates a new read-only instance of Address, bound to a specific deployed contract. +func NewAddressCaller(address common.Address, caller bind.ContractCaller) (*AddressCaller, error) { + contract, err := bindAddress(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &AddressCaller{contract: contract}, nil +} - logs, sub, err := _Admin.contract.WatchLogs(opts, "FeeRateUpdated") +// NewAddressTransactor creates a new write-only instance of Address, bound to a specific deployed contract. +func NewAddressTransactor(address common.Address, transactor bind.ContractTransactor) (*AddressTransactor, error) { + contract, err := bindAddress(address, nil, transactor, nil) if err != nil { return nil, err } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminFeeRateUpdated) - if err := _Admin.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { - return err - } - event.Raw = log + return &AddressTransactor{contract: contract}, nil +} - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil +// NewAddressFilterer creates a new log filterer instance of Address, bound to a specific deployed contract. +func NewAddressFilterer(address common.Address, filterer bind.ContractFilterer) (*AddressFilterer, error) { + contract, err := bindAddress(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &AddressFilterer{contract: contract}, nil } -// ParseFeeRateUpdated is a log parse operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. -// -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_Admin *AdminFilterer) ParseFeeRateUpdated(log types.Log) (*AdminFeeRateUpdated, error) { - event := new(AdminFeeRateUpdated) - if err := _Admin.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { +// bindAddress binds a generic wrapper to an already deployed contract. +func bindAddress(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := AddressMetaData.GetAbi() + if err != nil { return nil, err } - event.Raw = log - return event, nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } -// AdminFeesSweptIterator is returned from FilterFeesSwept and is used to iterate over the raw logs and unpacked data for FeesSwept events raised by the Admin contract. -type AdminFeesSweptIterator struct { - Event *AdminFeesSwept // Event containing the contract specifics and raw log +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Address *AddressRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Address.Contract.AddressCaller.contract.Call(opts, result, method, params...) +} - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Address *AddressRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Address.Contract.AddressTransactor.contract.Transfer(opts) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminFeesSweptIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminFeesSwept) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminFeesSwept) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// Transact invokes the (paid) contract method with params as input values. +func (_Address *AddressRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Address.Contract.AddressTransactor.contract.Transact(opts, method, params...) +} - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Address *AddressCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Address.Contract.contract.Call(opts, result, method, params...) } -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminFeesSweptIterator) Error() error { - return it.fail +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Address *AddressTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Address.Contract.contract.Transfer(opts) } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminFeesSweptIterator) Close() error { - it.sub.Unsubscribe() - return nil +// Transact invokes the (paid) contract method with params as input values. +func (_Address *AddressTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Address.Contract.contract.Transact(opts, method, params...) } -// AdminFeesSwept represents a FeesSwept event raised by the Admin contract. -type AdminFeesSwept struct { - Token common.Address - Recipient common.Address - Amount *big.Int - Raw types.Log // Blockchain specific contextual infos +// AdminMetaData contains all meta data concerning the Admin contract. +var AdminMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REFUNDER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "a217fddf": "DEFAULT_ADMIN_ROLE()", + "bf333f2c": "FEE_BPS()", + "0f5f6ed7": "FEE_RATE_MAX()", + "ccc57490": "GOVERNOR_ROLE()", + "03ed0ee5": "GUARD_ROLE()", + "5960ccf2": "REFUNDER_ROLE()", + "926d7d7f": "RELAYER_ROLE()", + "e00a83e0": "chainGasAmount()", + "248a9ca3": "getRoleAdmin(bytes32)", + "9010d07c": "getRoleMember(bytes32,uint256)", + "ca15c873": "getRoleMemberCount(bytes32)", + "2f2ff15d": "grantRole(bytes32,address)", + "91d14854": "hasRole(bytes32,address)", + "58f85880": "protocolFeeRate()", + "dcf844a7": "protocolFees(address)", + "36568abe": "renounceRole(bytes32,address)", + "d547741f": "revokeRole(bytes32,address)", + "b250fe6b": "setChainGasAmount(uint256)", + "b13aa2d6": "setProtocolFeeRate(uint256)", + "01ffc9a7": "supportsInterface(bytes4)", + "06f333f2": "sweepProtocolFees(address,address)", + }, + Bin: "0x60806040523480156200001157600080fd5b50604051620014123803806200141283398101604081905262000034916200018e565b6200004160008262000049565b5050620001b9565b60008062000058848462000086565b905080156200007d5760008481526001602052604090206200007b908462000134565b505b90505b92915050565b6000828152602081815260408083206001600160a01b038516845290915281205460ff166200012b576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620000e23390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600162000080565b50600062000080565b60006200007d836001600160a01b03841660008181526001830160205260408120546200012b5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000080565b600060208284031215620001a157600080fd5b81516001600160a01b03811681146200007d57600080fd5b61124980620001c96000396000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806391d14854116100d8578063bf333f2c1161008c578063d547741f11610066578063d547741f14610385578063dcf844a714610398578063e00a83e0146103b857600080fd5b8063bf333f2c14610341578063ca15c8731461034b578063ccc574901461035e57600080fd5b8063a217fddf116100bd578063a217fddf14610313578063b13aa2d61461031b578063b250fe6b1461032e57600080fd5b806391d14854146102a8578063926d7d7f146102ec57600080fd5b80632f2ff15d1161012f57806358f858801161011457806358f85880146102405780635960ccf2146102495780639010d07c1461027057600080fd5b80632f2ff15d1461021a57806336568abe1461022d57600080fd5b806306f333f21161016057806306f333f2146101d95780630f5f6ed7146101ee578063248a9ca3146101f757600080fd5b806301ffc9a71461017c57806303ed0ee5146101a4575b600080fd5b61018f61018a366004611013565b6103c1565b60405190151581526020015b60405180910390f35b6101cb7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b60405190815260200161019b565b6101ec6101e736600461107e565b61041d565b005b6101cb61271081565b6101cb6102053660046110b1565b60009081526020819052604090206001015490565b6101ec6102283660046110ca565b61050b565b6101ec61023b3660046110ca565b610536565b6101cb60025481565b6101cb7fdb9556138406326f00296e13ea2ad7db24ba82381212d816b1a40c23b466b32781565b61028361027e3660046110ed565b61058f565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b61018f6102b63660046110ca565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6101cb7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b6101cb600081565b6101ec6103293660046110b1565b6105ae565b6101ec61033c3660046110b1565b610690565b6101cb620f424081565b6101cb6103593660046110b1565b6106f8565b6101cb7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b6101ec6103933660046110ca565b61070f565b6101cb6103a636600461110f565b60036020526000908152604090205481565b6101cb60045481565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f000000000000000000000000000000000000000000000000000000001480610417575061041782610734565b92915050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55610447816107cb565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120549081900361047b5750505050565b73ffffffffffffffffffffffffffffffffffffffff84166000818152600360205260408120556104ac9084836107d8565b6040805173ffffffffffffffffffffffffffffffffffffffff8087168252851660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b505050565b600082815260208190526040902060010154610526816107cb565b610530838361092f565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610585576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105068282610964565b60008281526001602052604081206105a79083610991565b9392505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556105d8816107cb565b612710821115610649576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064015b60405180910390fd5b600280549083905560408051828152602081018590527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a1505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556106ba816107cb565b600480549083905560408051828152602081018590527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa9101610683565b60008181526001602052604081206104179061099d565b60008281526020819052604090206001015461072a816107cb565b6105308383610964565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061041757507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610417565b6107d581336109a7565b50565b3073ffffffffffffffffffffffffffffffffffffffff8316036107fa57505050565b8060000361080757505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff84160161090e5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461089e576040519150601f19603f3d011682016040523d82523d6000602084013e6108a3565b606091505b5050905080610530576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c6564000000000000000000000000006044820152606401610640565b61050673ffffffffffffffffffffffffffffffffffffffff84168383610a31565b60008061093c8484610abe565b905080156105a757600084815260016020526040902061095c9084610bba565b509392505050565b6000806109718484610bdc565b905080156105a757600084815260016020526040902061095c9084610c97565b60006105a78383610cb9565b6000610417825490565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610a2d576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260248101839052604401610640565b5050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610506908490610ce3565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16610bb25760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610b503390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610417565b506000610417565b60006105a78373ffffffffffffffffffffffffffffffffffffffff8416610d79565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff1615610bb25760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610417565b60006105a78373ffffffffffffffffffffffffffffffffffffffff8416610dc0565b6000826000018281548110610cd057610cd061112a565b9060005260206000200154905092915050565b6000610d0573ffffffffffffffffffffffffffffffffffffffff841683610eb3565b90508051600014158015610d2a575080806020019051810190610d289190611159565b155b15610506576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610640565b6000818152600183016020526040812054610bb257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610417565b60008181526001830160205260408120548015610ea9576000610de460018361117b565b8554909150600090610df89060019061117b565b9050808214610e5d576000866000018281548110610e1857610e1861112a565b9060005260206000200154905080876000018481548110610e3b57610e3b61112a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080610e6e57610e6e6111b5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610417565b6000915050610417565b60606105a783836000846000808573ffffffffffffffffffffffffffffffffffffffff168486604051610ee691906111e4565b60006040518083038185875af1925050503d8060008114610f23576040519150601f19603f3d011682016040523d82523d6000602084013e610f28565b606091505b5091509150610f38868383610f42565b9695505050505050565b606082610f5757610f5282610fd1565b6105a7565b8151158015610f7b575073ffffffffffffffffffffffffffffffffffffffff84163b155b15610fca576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610640565b50806105a7565b805115610fe15780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561102557600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146105a757600080fd5b803573ffffffffffffffffffffffffffffffffffffffff8116811461107957600080fd5b919050565b6000806040838503121561109157600080fd5b61109a83611055565b91506110a860208401611055565b90509250929050565b6000602082840312156110c357600080fd5b5035919050565b600080604083850312156110dd57600080fd5b823591506110a860208401611055565b6000806040838503121561110057600080fd5b50508035926020909101359150565b60006020828403121561112157600080fd5b6105a782611055565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561116b57600080fd5b815180151581146105a757600080fd5b81810381811115610417577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000825160005b8181101561120557602081860181015185830152016111eb565b50600092019182525091905056fea2646970667358221220ae622a2da80c730eb06fbc09f0feabbb824bbdb349894cba40b3bf6d93d73db164736f6c63430008140033", } -// FilterFeesSwept is a free log retrieval operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. -// -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_Admin *AdminFilterer) FilterFeesSwept(opts *bind.FilterOpts) (*AdminFeesSweptIterator, error) { +// AdminABI is the input ABI used to generate the binding from. +// Deprecated: Use AdminMetaData.ABI instead. +var AdminABI = AdminMetaData.ABI - logs, sub, err := _Admin.contract.FilterLogs(opts, "FeesSwept") - if err != nil { - return nil, err - } - return &AdminFeesSweptIterator{contract: _Admin.contract, event: "FeesSwept", logs: logs, sub: sub}, nil -} +// Deprecated: Use AdminMetaData.Sigs instead. +// AdminFuncSigs maps the 4-byte function signature to its string representation. +var AdminFuncSigs = AdminMetaData.Sigs -// WatchFeesSwept is a free log subscription operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. -// -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_Admin *AdminFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink chan<- *AdminFeesSwept) (event.Subscription, error) { +// AdminBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use AdminMetaData.Bin instead. +var AdminBin = AdminMetaData.Bin - logs, sub, err := _Admin.contract.WatchLogs(opts, "FeesSwept") +// DeployAdmin deploys a new Ethereum contract, binding an instance of Admin to it. +func DeployAdmin(auth *bind.TransactOpts, backend bind.ContractBackend, _owner common.Address) (common.Address, *types.Transaction, *Admin, error) { + parsed, err := AdminMetaData.GetAbi() if err != nil { - return nil, err + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminFeesSwept) - if err := _Admin.contract.UnpackLog(event, "FeesSwept", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} -// ParseFeesSwept is a log parse operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. -// -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_Admin *AdminFilterer) ParseFeesSwept(log types.Log) (*AdminFeesSwept, error) { - event := new(AdminFeesSwept) - if err := _Admin.contract.UnpackLog(event, "FeesSwept", log); err != nil { - return nil, err + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(AdminBin), backend, _owner) + if err != nil { + return common.Address{}, nil, nil, err } - event.Raw = log - return event, nil + return address, tx, &Admin{AdminCaller: AdminCaller{contract: contract}, AdminTransactor: AdminTransactor{contract: contract}, AdminFilterer: AdminFilterer{contract: contract}}, nil } -// AdminGovernorAddedIterator is returned from FilterGovernorAdded and is used to iterate over the raw logs and unpacked data for GovernorAdded events raised by the Admin contract. -type AdminGovernorAddedIterator struct { - Event *AdminGovernorAdded // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// Admin is an auto generated Go binding around an Ethereum contract. +type Admin struct { + AdminCaller // Read-only binding to the contract + AdminTransactor // Write-only binding to the contract + AdminFilterer // Log filterer for contract events } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminGovernorAddedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminGovernorAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminGovernorAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } +// AdminCaller is an auto generated read-only Go binding around an Ethereum contract. +type AdminCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminGovernorAddedIterator) Error() error { - return it.fail +// AdminTransactor is an auto generated write-only Go binding around an Ethereum contract. +type AdminTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminGovernorAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// AdminFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type AdminFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// AdminGovernorAdded represents a GovernorAdded event raised by the Admin contract. -type AdminGovernorAdded struct { - Governor common.Address - Raw types.Log // Blockchain specific contextual infos +// AdminSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type AdminSession struct { + Contract *Admin // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// FilterGovernorAdded is a free log retrieval operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. -// -// Solidity: event GovernorAdded(address governor) -func (_Admin *AdminFilterer) FilterGovernorAdded(opts *bind.FilterOpts) (*AdminGovernorAddedIterator, error) { - - logs, sub, err := _Admin.contract.FilterLogs(opts, "GovernorAdded") - if err != nil { - return nil, err - } - return &AdminGovernorAddedIterator{contract: _Admin.contract, event: "GovernorAdded", logs: logs, sub: sub}, nil +// AdminCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type AdminCallerSession struct { + Contract *AdminCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session } -// WatchGovernorAdded is a free log subscription operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. -// -// Solidity: event GovernorAdded(address governor) -func (_Admin *AdminFilterer) WatchGovernorAdded(opts *bind.WatchOpts, sink chan<- *AdminGovernorAdded) (event.Subscription, error) { - - logs, sub, err := _Admin.contract.WatchLogs(opts, "GovernorAdded") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminGovernorAdded) - if err := _Admin.contract.UnpackLog(event, "GovernorAdded", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseGovernorAdded is a log parse operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. -// -// Solidity: event GovernorAdded(address governor) -func (_Admin *AdminFilterer) ParseGovernorAdded(log types.Log) (*AdminGovernorAdded, error) { - event := new(AdminGovernorAdded) - if err := _Admin.contract.UnpackLog(event, "GovernorAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// AdminTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type AdminTransactorSession struct { + Contract *AdminTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// AdminGovernorRemovedIterator is returned from FilterGovernorRemoved and is used to iterate over the raw logs and unpacked data for GovernorRemoved events raised by the Admin contract. -type AdminGovernorRemovedIterator struct { - Event *AdminGovernorRemoved // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// AdminRaw is an auto generated low-level Go binding around an Ethereum contract. +type AdminRaw struct { + Contract *Admin // Generic contract binding to access the raw methods on } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminGovernorRemovedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminGovernorRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminGovernorRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } +// AdminCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type AdminCallerRaw struct { + Contract *AdminCaller // Generic read-only contract binding to access the raw methods on } -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminGovernorRemovedIterator) Error() error { - return it.fail +// AdminTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type AdminTransactorRaw struct { + Contract *AdminTransactor // Generic write-only contract binding to access the raw methods on } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminGovernorRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// NewAdmin creates a new instance of Admin, bound to a specific deployed contract. +func NewAdmin(address common.Address, backend bind.ContractBackend) (*Admin, error) { + contract, err := bindAdmin(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Admin{AdminCaller: AdminCaller{contract: contract}, AdminTransactor: AdminTransactor{contract: contract}, AdminFilterer: AdminFilterer{contract: contract}}, nil } -// AdminGovernorRemoved represents a GovernorRemoved event raised by the Admin contract. -type AdminGovernorRemoved struct { - Governor common.Address - Raw types.Log // Blockchain specific contextual infos +// NewAdminCaller creates a new read-only instance of Admin, bound to a specific deployed contract. +func NewAdminCaller(address common.Address, caller bind.ContractCaller) (*AdminCaller, error) { + contract, err := bindAdmin(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &AdminCaller{contract: contract}, nil } -// FilterGovernorRemoved is a free log retrieval operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. -// -// Solidity: event GovernorRemoved(address governor) -func (_Admin *AdminFilterer) FilterGovernorRemoved(opts *bind.FilterOpts) (*AdminGovernorRemovedIterator, error) { - - logs, sub, err := _Admin.contract.FilterLogs(opts, "GovernorRemoved") +// NewAdminTransactor creates a new write-only instance of Admin, bound to a specific deployed contract. +func NewAdminTransactor(address common.Address, transactor bind.ContractTransactor) (*AdminTransactor, error) { + contract, err := bindAdmin(address, nil, transactor, nil) if err != nil { return nil, err } - return &AdminGovernorRemovedIterator{contract: _Admin.contract, event: "GovernorRemoved", logs: logs, sub: sub}, nil + return &AdminTransactor{contract: contract}, nil } -// WatchGovernorRemoved is a free log subscription operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. -// -// Solidity: event GovernorRemoved(address governor) -func (_Admin *AdminFilterer) WatchGovernorRemoved(opts *bind.WatchOpts, sink chan<- *AdminGovernorRemoved) (event.Subscription, error) { - - logs, sub, err := _Admin.contract.WatchLogs(opts, "GovernorRemoved") +// NewAdminFilterer creates a new log filterer instance of Admin, bound to a specific deployed contract. +func NewAdminFilterer(address common.Address, filterer bind.ContractFilterer) (*AdminFilterer, error) { + contract, err := bindAdmin(address, nil, nil, filterer) if err != nil { return nil, err } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminGovernorRemoved) - if err := _Admin.contract.UnpackLog(event, "GovernorRemoved", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil + return &AdminFilterer{contract: contract}, nil } -// ParseGovernorRemoved is a log parse operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. -// -// Solidity: event GovernorRemoved(address governor) -func (_Admin *AdminFilterer) ParseGovernorRemoved(log types.Log) (*AdminGovernorRemoved, error) { - event := new(AdminGovernorRemoved) - if err := _Admin.contract.UnpackLog(event, "GovernorRemoved", log); err != nil { +// bindAdmin binds a generic wrapper to an already deployed contract. +func bindAdmin(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := AdminMetaData.GetAbi() + if err != nil { return nil, err } - event.Raw = log - return event, nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } -// AdminGuardAddedIterator is returned from FilterGuardAdded and is used to iterate over the raw logs and unpacked data for GuardAdded events raised by the Admin contract. -type AdminGuardAddedIterator struct { - Event *AdminGuardAdded // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Admin *AdminRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Admin.Contract.AdminCaller.contract.Call(opts, result, method, params...) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminGuardAddedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminGuardAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminGuardAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Admin *AdminRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Admin.Contract.AdminTransactor.contract.Transfer(opts) +} - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } +// Transact invokes the (paid) contract method with params as input values. +func (_Admin *AdminRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Admin.Contract.AdminTransactor.contract.Transact(opts, method, params...) } -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminGuardAddedIterator) Error() error { - return it.fail +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Admin *AdminCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Admin.Contract.contract.Call(opts, result, method, params...) } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminGuardAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Admin *AdminTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Admin.Contract.contract.Transfer(opts) } -// AdminGuardAdded represents a GuardAdded event raised by the Admin contract. -type AdminGuardAdded struct { - Guard common.Address - Raw types.Log // Blockchain specific contextual infos +// Transact invokes the (paid) contract method with params as input values. +func (_Admin *AdminTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Admin.Contract.contract.Transact(opts, method, params...) } -// FilterGuardAdded is a free log retrieval operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. // -// Solidity: event GuardAdded(address guard) -func (_Admin *AdminFilterer) FilterGuardAdded(opts *bind.FilterOpts) (*AdminGuardAddedIterator, error) { +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_Admin *AdminCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") - logs, sub, err := _Admin.contract.FilterLogs(opts, "GuardAdded") if err != nil { - return nil, err + return *new([32]byte), err } - return &AdminGuardAddedIterator{contract: _Admin.contract, event: "GuardAdded", logs: logs, sub: sub}, nil + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -// WatchGuardAdded is a free log subscription operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. // -// Solidity: event GuardAdded(address guard) -func (_Admin *AdminFilterer) WatchGuardAdded(opts *bind.WatchOpts, sink chan<- *AdminGuardAdded) (event.Subscription, error) { +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_Admin *AdminSession) DEFAULTADMINROLE() ([32]byte, error) { + return _Admin.Contract.DEFAULTADMINROLE(&_Admin.CallOpts) +} - logs, sub, err := _Admin.contract.WatchLogs(opts, "GuardAdded") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminGuardAdded) - if err := _Admin.contract.UnpackLog(event, "GuardAdded", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_Admin *AdminCallerSession) DEFAULTADMINROLE() ([32]byte, error) { + return _Admin.Contract.DEFAULTADMINROLE(&_Admin.CallOpts) } -// ParseGuardAdded is a log parse operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. // -// Solidity: event GuardAdded(address guard) -func (_Admin *AdminFilterer) ParseGuardAdded(log types.Log) (*AdminGuardAdded, error) { - event := new(AdminGuardAdded) - if err := _Admin.contract.UnpackLog(event, "GuardAdded", log); err != nil { - return nil, err +// Solidity: function FEE_BPS() view returns(uint256) +func (_Admin *AdminCaller) FEEBPS(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "FEE_BPS") + + if err != nil { + return *new(*big.Int), err } - event.Raw = log - return event, nil -} -// AdminGuardRemovedIterator is returned from FilterGuardRemoved and is used to iterate over the raw logs and unpacked data for GuardRemoved events raised by the Admin contract. -type AdminGuardRemovedIterator struct { - Event *AdminGuardRemoved // Event containing the contract specifics and raw log + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data + return out0, err - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminGuardRemovedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminGuardRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. +// +// Solidity: function FEE_BPS() view returns(uint256) +func (_Admin *AdminSession) FEEBPS() (*big.Int, error) { + return _Admin.Contract.FEEBPS(&_Admin.CallOpts) +} - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminGuardRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. +// +// Solidity: function FEE_BPS() view returns(uint256) +func (_Admin *AdminCallerSession) FEEBPS() (*big.Int, error) { + return _Admin.Contract.FEEBPS(&_Admin.CallOpts) +} - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() +// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. +// +// Solidity: function FEE_RATE_MAX() view returns(uint256) +func (_Admin *AdminCaller) FEERATEMAX(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "FEE_RATE_MAX") + + if err != nil { + return *new(*big.Int), err } -} -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminGuardRemovedIterator) Error() error { - return it.fail -} + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminGuardRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} + return out0, err -// AdminGuardRemoved represents a GuardRemoved event raised by the Admin contract. -type AdminGuardRemoved struct { - Guard common.Address - Raw types.Log // Blockchain specific contextual infos } -// FilterGuardRemoved is a free log retrieval operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. // -// Solidity: event GuardRemoved(address guard) -func (_Admin *AdminFilterer) FilterGuardRemoved(opts *bind.FilterOpts) (*AdminGuardRemovedIterator, error) { +// Solidity: function FEE_RATE_MAX() view returns(uint256) +func (_Admin *AdminSession) FEERATEMAX() (*big.Int, error) { + return _Admin.Contract.FEERATEMAX(&_Admin.CallOpts) +} - logs, sub, err := _Admin.contract.FilterLogs(opts, "GuardRemoved") - if err != nil { - return nil, err - } - return &AdminGuardRemovedIterator{contract: _Admin.contract, event: "GuardRemoved", logs: logs, sub: sub}, nil +// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. +// +// Solidity: function FEE_RATE_MAX() view returns(uint256) +func (_Admin *AdminCallerSession) FEERATEMAX() (*big.Int, error) { + return _Admin.Contract.FEERATEMAX(&_Admin.CallOpts) } -// WatchGuardRemoved is a free log subscription operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. // -// Solidity: event GuardRemoved(address guard) -func (_Admin *AdminFilterer) WatchGuardRemoved(opts *bind.WatchOpts, sink chan<- *AdminGuardRemoved) (event.Subscription, error) { +// Solidity: function GOVERNOR_ROLE() view returns(bytes32) +func (_Admin *AdminCaller) GOVERNORROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "GOVERNOR_ROLE") - logs, sub, err := _Admin.contract.WatchLogs(opts, "GuardRemoved") if err != nil { - return nil, err + return *new([32]byte), err } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminGuardRemoved) - if err := _Admin.contract.UnpackLog(event, "GuardRemoved", log); err != nil { - return err - } - event.Raw = log - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -// ParseGuardRemoved is a log parse operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. // -// Solidity: event GuardRemoved(address guard) -func (_Admin *AdminFilterer) ParseGuardRemoved(log types.Log) (*AdminGuardRemoved, error) { - event := new(AdminGuardRemoved) - if err := _Admin.contract.UnpackLog(event, "GuardRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function GOVERNOR_ROLE() view returns(bytes32) +func (_Admin *AdminSession) GOVERNORROLE() ([32]byte, error) { + return _Admin.Contract.GOVERNORROLE(&_Admin.CallOpts) } -// AdminRelayerAddedIterator is returned from FilterRelayerAdded and is used to iterate over the raw logs and unpacked data for RelayerAdded events raised by the Admin contract. -type AdminRelayerAddedIterator struct { - Event *AdminRelayerAdded // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. +// +// Solidity: function GOVERNOR_ROLE() view returns(bytes32) +func (_Admin *AdminCallerSession) GOVERNORROLE() ([32]byte, error) { + return _Admin.Contract.GOVERNORROLE(&_Admin.CallOpts) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminRelayerAddedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminRelayerAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. +// +// Solidity: function GUARD_ROLE() view returns(bytes32) +func (_Admin *AdminCaller) GUARDROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "GUARD_ROLE") - default: - return false - } + if err != nil { + return *new([32]byte), err } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminRelayerAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminRelayerAddedIterator) Error() error { - return it.fail } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminRelayerAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. +// +// Solidity: function GUARD_ROLE() view returns(bytes32) +func (_Admin *AdminSession) GUARDROLE() ([32]byte, error) { + return _Admin.Contract.GUARDROLE(&_Admin.CallOpts) } -// AdminRelayerAdded represents a RelayerAdded event raised by the Admin contract. -type AdminRelayerAdded struct { - Relayer common.Address - Raw types.Log // Blockchain specific contextual infos +// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. +// +// Solidity: function GUARD_ROLE() view returns(bytes32) +func (_Admin *AdminCallerSession) GUARDROLE() ([32]byte, error) { + return _Admin.Contract.GUARDROLE(&_Admin.CallOpts) } -// FilterRelayerAdded is a free log retrieval operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// REFUNDERROLE is a free data retrieval call binding the contract method 0x5960ccf2. // -// Solidity: event RelayerAdded(address relayer) -func (_Admin *AdminFilterer) FilterRelayerAdded(opts *bind.FilterOpts) (*AdminRelayerAddedIterator, error) { +// Solidity: function REFUNDER_ROLE() view returns(bytes32) +func (_Admin *AdminCaller) REFUNDERROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "REFUNDER_ROLE") - logs, sub, err := _Admin.contract.FilterLogs(opts, "RelayerAdded") if err != nil { - return nil, err + return *new([32]byte), err } - return &AdminRelayerAddedIterator{contract: _Admin.contract, event: "RelayerAdded", logs: logs, sub: sub}, nil + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -// WatchRelayerAdded is a free log subscription operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// REFUNDERROLE is a free data retrieval call binding the contract method 0x5960ccf2. // -// Solidity: event RelayerAdded(address relayer) -func (_Admin *AdminFilterer) WatchRelayerAdded(opts *bind.WatchOpts, sink chan<- *AdminRelayerAdded) (event.Subscription, error) { +// Solidity: function REFUNDER_ROLE() view returns(bytes32) +func (_Admin *AdminSession) REFUNDERROLE() ([32]byte, error) { + return _Admin.Contract.REFUNDERROLE(&_Admin.CallOpts) +} + +// REFUNDERROLE is a free data retrieval call binding the contract method 0x5960ccf2. +// +// Solidity: function REFUNDER_ROLE() view returns(bytes32) +func (_Admin *AdminCallerSession) REFUNDERROLE() ([32]byte, error) { + return _Admin.Contract.REFUNDERROLE(&_Admin.CallOpts) +} + +// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. +// +// Solidity: function RELAYER_ROLE() view returns(bytes32) +func (_Admin *AdminCaller) RELAYERROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "RELAYER_ROLE") - logs, sub, err := _Admin.contract.WatchLogs(opts, "RelayerAdded") if err != nil { - return nil, err + return *new([32]byte), err } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminRelayerAdded) - if err := _Admin.contract.UnpackLog(event, "RelayerAdded", log); err != nil { - return err - } - event.Raw = log - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -// ParseRelayerAdded is a log parse operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. // -// Solidity: event RelayerAdded(address relayer) -func (_Admin *AdminFilterer) ParseRelayerAdded(log types.Log) (*AdminRelayerAdded, error) { - event := new(AdminRelayerAdded) - if err := _Admin.contract.UnpackLog(event, "RelayerAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function RELAYER_ROLE() view returns(bytes32) +func (_Admin *AdminSession) RELAYERROLE() ([32]byte, error) { + return _Admin.Contract.RELAYERROLE(&_Admin.CallOpts) } -// AdminRelayerRemovedIterator is returned from FilterRelayerRemoved and is used to iterate over the raw logs and unpacked data for RelayerRemoved events raised by the Admin contract. -type AdminRelayerRemovedIterator struct { - Event *AdminRelayerRemoved // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. +// +// Solidity: function RELAYER_ROLE() view returns(bytes32) +func (_Admin *AdminCallerSession) RELAYERROLE() ([32]byte, error) { + return _Admin.Contract.RELAYERROLE(&_Admin.CallOpts) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminRelayerRemovedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminRelayerRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. +// +// Solidity: function chainGasAmount() view returns(uint256) +func (_Admin *AdminCaller) ChainGasAmount(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "chainGasAmount") - default: - return false - } + if err != nil { + return *new(*big.Int), err } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminRelayerRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminRelayerRemovedIterator) Error() error { - return it.fail } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminRelayerRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. +// +// Solidity: function chainGasAmount() view returns(uint256) +func (_Admin *AdminSession) ChainGasAmount() (*big.Int, error) { + return _Admin.Contract.ChainGasAmount(&_Admin.CallOpts) } -// AdminRelayerRemoved represents a RelayerRemoved event raised by the Admin contract. -type AdminRelayerRemoved struct { - Relayer common.Address - Raw types.Log // Blockchain specific contextual infos +// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. +// +// Solidity: function chainGasAmount() view returns(uint256) +func (_Admin *AdminCallerSession) ChainGasAmount() (*big.Int, error) { + return _Admin.Contract.ChainGasAmount(&_Admin.CallOpts) } -// FilterRelayerRemoved is a free log retrieval operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. // -// Solidity: event RelayerRemoved(address relayer) -func (_Admin *AdminFilterer) FilterRelayerRemoved(opts *bind.FilterOpts) (*AdminRelayerRemovedIterator, error) { +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_Admin *AdminCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "getRoleAdmin", role) - logs, sub, err := _Admin.contract.FilterLogs(opts, "RelayerRemoved") if err != nil { - return nil, err + return *new([32]byte), err } - return &AdminRelayerRemovedIterator{contract: _Admin.contract, event: "RelayerRemoved", logs: logs, sub: sub}, nil + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_Admin *AdminSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _Admin.Contract.GetRoleAdmin(&_Admin.CallOpts, role) +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_Admin *AdminCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _Admin.Contract.GetRoleAdmin(&_Admin.CallOpts, role) } -// WatchRelayerRemoved is a free log subscription operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. // -// Solidity: event RelayerRemoved(address relayer) -func (_Admin *AdminFilterer) WatchRelayerRemoved(opts *bind.WatchOpts, sink chan<- *AdminRelayerRemoved) (event.Subscription, error) { +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_Admin *AdminCaller) GetRoleMember(opts *bind.CallOpts, role [32]byte, index *big.Int) (common.Address, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "getRoleMember", role, index) - logs, sub, err := _Admin.contract.WatchLogs(opts, "RelayerRemoved") if err != nil { - return nil, err + return *new(common.Address), err } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminRelayerRemoved) - if err := _Admin.contract.UnpackLog(event, "RelayerRemoved", log); err != nil { - return err - } - event.Raw = log - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + } -// ParseRelayerRemoved is a log parse operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. // -// Solidity: event RelayerRemoved(address relayer) -func (_Admin *AdminFilterer) ParseRelayerRemoved(log types.Log) (*AdminRelayerRemoved, error) { - event := new(AdminRelayerRemoved) - if err := _Admin.contract.UnpackLog(event, "RelayerRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_Admin *AdminSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _Admin.Contract.GetRoleMember(&_Admin.CallOpts, role, index) } -// AdminRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the Admin contract. -type AdminRoleAdminChangedIterator struct { - Event *AdminRoleAdminChanged // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. +// +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_Admin *AdminCallerSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _Admin.Contract.GetRoleMember(&_Admin.CallOpts, role, index) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminRoleAdminChangedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminRoleAdminChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. +// +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_Admin *AdminCaller) GetRoleMemberCount(opts *bind.CallOpts, role [32]byte) (*big.Int, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "getRoleMemberCount", role) - default: - return false - } + if err != nil { + return *new(*big.Int), err } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminRoleAdminChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminRoleAdminChangedIterator) Error() error { - return it.fail -} + return out0, err -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminRoleAdminChangedIterator) Close() error { - it.sub.Unsubscribe() - return nil } -// AdminRoleAdminChanged represents a RoleAdminChanged event raised by the Admin contract. -type AdminRoleAdminChanged struct { - Role [32]byte - PreviousAdminRole [32]byte - NewAdminRole [32]byte - Raw types.Log // Blockchain specific contextual infos +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. +// +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_Admin *AdminSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _Admin.Contract.GetRoleMemberCount(&_Admin.CallOpts, role) } -// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. // -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_Admin *AdminFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*AdminRoleAdminChangedIterator, error) { +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_Admin *AdminCallerSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _Admin.Contract.GetRoleMemberCount(&_Admin.CallOpts, role) +} - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var previousAdminRoleRule []interface{} - for _, previousAdminRoleItem := range previousAdminRole { - previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) - } - var newAdminRoleRule []interface{} - for _, newAdminRoleItem := range newAdminRole { - newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) - } +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_Admin *AdminCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "hasRole", role, account) - logs, sub, err := _Admin.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { - return nil, err + return *new(bool), err } - return &AdminRoleAdminChangedIterator{contract: _Admin.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + } -// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// HasRole is a free data retrieval call binding the contract method 0x91d14854. // -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_Admin *AdminFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *AdminRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_Admin *AdminSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _Admin.Contract.HasRole(&_Admin.CallOpts, role, account) +} - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var previousAdminRoleRule []interface{} - for _, previousAdminRoleItem := range previousAdminRole { - previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) - } - var newAdminRoleRule []interface{} - for _, newAdminRoleItem := range newAdminRole { - newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) - } +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_Admin *AdminCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _Admin.Contract.HasRole(&_Admin.CallOpts, role, account) +} + +// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// +// Solidity: function protocolFeeRate() view returns(uint256) +func (_Admin *AdminCaller) ProtocolFeeRate(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "protocolFeeRate") - logs, sub, err := _Admin.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { - return nil, err + return *new(*big.Int), err } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminRoleAdminChanged) - if err := _Admin.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { - return err - } - event.Raw = log - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. // -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_Admin *AdminFilterer) ParseRoleAdminChanged(log types.Log) (*AdminRoleAdminChanged, error) { - event := new(AdminRoleAdminChanged) - if err := _Admin.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function protocolFeeRate() view returns(uint256) +func (_Admin *AdminSession) ProtocolFeeRate() (*big.Int, error) { + return _Admin.Contract.ProtocolFeeRate(&_Admin.CallOpts) } -// AdminRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the Admin contract. -type AdminRoleGrantedIterator struct { - Event *AdminRoleGranted // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// +// Solidity: function protocolFeeRate() view returns(uint256) +func (_Admin *AdminCallerSession) ProtocolFeeRate() (*big.Int, error) { + return _Admin.Contract.ProtocolFeeRate(&_Admin.CallOpts) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminRoleGrantedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminRoleGranted) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. +// +// Solidity: function protocolFees(address ) view returns(uint256) +func (_Admin *AdminCaller) ProtocolFees(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "protocolFees", arg0) - default: - return false - } + if err != nil { + return *new(*big.Int), err } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminRoleGranted) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminRoleGrantedIterator) Error() error { - return it.fail -} + return out0, err -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminRoleGrantedIterator) Close() error { - it.sub.Unsubscribe() - return nil } -// AdminRoleGranted represents a RoleGranted event raised by the Admin contract. -type AdminRoleGranted struct { - Role [32]byte - Account common.Address - Sender common.Address - Raw types.Log // Blockchain specific contextual infos +// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. +// +// Solidity: function protocolFees(address ) view returns(uint256) +func (_Admin *AdminSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { + return _Admin.Contract.ProtocolFees(&_Admin.CallOpts, arg0) } -// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. // -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_Admin *AdminFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*AdminRoleGrantedIterator, error) { +// Solidity: function protocolFees(address ) view returns(uint256) +func (_Admin *AdminCallerSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { + return _Admin.Contract.ProtocolFees(&_Admin.CallOpts, arg0) +} - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Admin *AdminCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "supportsInterface", interfaceId) - logs, sub, err := _Admin.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) if err != nil { - return nil, err + return *new(bool), err } - return &AdminRoleGrantedIterator{contract: _Admin.contract, event: "RoleGranted", logs: logs, sub: sub}, nil + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + } -// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_Admin *AdminFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *AdminRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Admin *AdminSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Admin.Contract.SupportsInterface(&_Admin.CallOpts, interfaceId) +} - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Admin *AdminCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Admin.Contract.SupportsInterface(&_Admin.CallOpts, interfaceId) +} - logs, sub, err := _Admin.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminRoleGranted) - if err := _Admin.contract.UnpackLog(event, "RoleGranted", log); err != nil { - return err - } - event.Raw = log +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_Admin *AdminTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _Admin.contract.Transact(opts, "grantRole", role, account) +} - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_Admin *AdminSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Admin.Contract.GrantRole(&_Admin.TransactOpts, role, account) } -// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. // -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_Admin *AdminFilterer) ParseRoleGranted(log types.Log) (*AdminRoleGranted, error) { - event := new(AdminRoleGranted) - if err := _Admin.contract.UnpackLog(event, "RoleGranted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_Admin *AdminTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Admin.Contract.GrantRole(&_Admin.TransactOpts, role, account) } -// AdminRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the Admin contract. -type AdminRoleRevokedIterator struct { - Event *AdminRoleRevoked // Event containing the contract specifics and raw log +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_Admin *AdminTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _Admin.contract.Transact(opts, "renounceRole", role, callerConfirmation) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_Admin *AdminSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _Admin.Contract.RenounceRole(&_Admin.TransactOpts, role, callerConfirmation) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_Admin *AdminTransactorSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _Admin.Contract.RenounceRole(&_Admin.TransactOpts, role, callerConfirmation) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_Admin *AdminTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _Admin.contract.Transact(opts, "revokeRole", role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_Admin *AdminSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Admin.Contract.RevokeRole(&_Admin.TransactOpts, role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_Admin *AdminTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Admin.Contract.RevokeRole(&_Admin.TransactOpts, role, account) +} + +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_Admin *AdminTransactor) SetChainGasAmount(opts *bind.TransactOpts, newChainGasAmount *big.Int) (*types.Transaction, error) { + return _Admin.contract.Transact(opts, "setChainGasAmount", newChainGasAmount) +} + +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_Admin *AdminSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { + return _Admin.Contract.SetChainGasAmount(&_Admin.TransactOpts, newChainGasAmount) +} + +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_Admin *AdminTransactorSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { + return _Admin.Contract.SetChainGasAmount(&_Admin.TransactOpts, newChainGasAmount) +} + +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. +// +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_Admin *AdminTransactor) SetProtocolFeeRate(opts *bind.TransactOpts, newFeeRate *big.Int) (*types.Transaction, error) { + return _Admin.contract.Transact(opts, "setProtocolFeeRate", newFeeRate) +} + +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. +// +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_Admin *AdminSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { + return _Admin.Contract.SetProtocolFeeRate(&_Admin.TransactOpts, newFeeRate) +} + +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. +// +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_Admin *AdminTransactorSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { + return _Admin.Contract.SetProtocolFeeRate(&_Admin.TransactOpts, newFeeRate) +} + +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_Admin *AdminTransactor) SweepProtocolFees(opts *bind.TransactOpts, token common.Address, recipient common.Address) (*types.Transaction, error) { + return _Admin.contract.Transact(opts, "sweepProtocolFees", token, recipient) +} + +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_Admin *AdminSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { + return _Admin.Contract.SweepProtocolFees(&_Admin.TransactOpts, token, recipient) +} + +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_Admin *AdminTransactorSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { + return _Admin.Contract.SweepProtocolFees(&_Admin.TransactOpts, token, recipient) +} + +// AdminChainGasAmountUpdatedIterator is returned from FilterChainGasAmountUpdated and is used to iterate over the raw logs and unpacked data for ChainGasAmountUpdated events raised by the Admin contract. +type AdminChainGasAmountUpdatedIterator struct { + Event *AdminChainGasAmountUpdated // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -3445,7 +2776,7 @@ type AdminRoleRevokedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *AdminRoleRevokedIterator) Next() bool { +func (it *AdminChainGasAmountUpdatedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -3454,7 +2785,7 @@ func (it *AdminRoleRevokedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(AdminRoleRevoked) + it.Event = new(AdminChainGasAmountUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -3469,7 +2800,7 @@ func (it *AdminRoleRevokedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(AdminRoleRevoked) + it.Event = new(AdminChainGasAmountUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -3485,69 +2816,42 @@ func (it *AdminRoleRevokedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminRoleRevokedIterator) Error() error { +func (it *AdminChainGasAmountUpdatedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *AdminRoleRevokedIterator) Close() error { +func (it *AdminChainGasAmountUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -// AdminRoleRevoked represents a RoleRevoked event raised by the Admin contract. -type AdminRoleRevoked struct { - Role [32]byte - Account common.Address - Sender common.Address - Raw types.Log // Blockchain specific contextual infos +// AdminChainGasAmountUpdated represents a ChainGasAmountUpdated event raised by the Admin contract. +type AdminChainGasAmountUpdated struct { + OldChainGasAmount *big.Int + NewChainGasAmount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// FilterChainGasAmountUpdated is a free log retrieval operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_Admin *AdminFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*AdminRoleRevokedIterator, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_Admin *AdminFilterer) FilterChainGasAmountUpdated(opts *bind.FilterOpts) (*AdminChainGasAmountUpdatedIterator, error) { - logs, sub, err := _Admin.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + logs, sub, err := _Admin.contract.FilterLogs(opts, "ChainGasAmountUpdated") if err != nil { return nil, err } - return &AdminRoleRevokedIterator{contract: _Admin.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil + return &AdminChainGasAmountUpdatedIterator{contract: _Admin.contract, event: "ChainGasAmountUpdated", logs: logs, sub: sub}, nil } -// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// WatchChainGasAmountUpdated is a free log subscription operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_Admin *AdminFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *AdminRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_Admin *AdminFilterer) WatchChainGasAmountUpdated(opts *bind.WatchOpts, sink chan<- *AdminChainGasAmountUpdated) (event.Subscription, error) { - logs, sub, err := _Admin.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + logs, sub, err := _Admin.contract.WatchLogs(opts, "ChainGasAmountUpdated") if err != nil { return nil, err } @@ -3557,8 +2861,8 @@ func (_Admin *AdminFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(AdminRoleRevoked) - if err := _Admin.contract.UnpackLog(event, "RoleRevoked", log); err != nil { + event := new(AdminChainGasAmountUpdated) + if err := _Admin.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { return err } event.Raw = log @@ -3579,1155 +2883,1541 @@ func (_Admin *AdminFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- }), nil } -// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// ParseChainGasAmountUpdated is a log parse operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_Admin *AdminFilterer) ParseRoleRevoked(log types.Log) (*AdminRoleRevoked, error) { - event := new(AdminRoleRevoked) - if err := _Admin.contract.UnpackLog(event, "RoleRevoked", log); err != nil { +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_Admin *AdminFilterer) ParseChainGasAmountUpdated(log types.Log) (*AdminChainGasAmountUpdated, error) { + event := new(AdminChainGasAmountUpdated) + if err := _Admin.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -// ContextMetaData contains all meta data concerning the Context contract. -var ContextMetaData = &bind.MetaData{ - ABI: "[]", -} +// AdminFeeRateUpdatedIterator is returned from FilterFeeRateUpdated and is used to iterate over the raw logs and unpacked data for FeeRateUpdated events raised by the Admin contract. +type AdminFeeRateUpdatedIterator struct { + Event *AdminFeeRateUpdated // Event containing the contract specifics and raw log -// ContextABI is the input ABI used to generate the binding from. -// Deprecated: Use ContextMetaData.ABI instead. -var ContextABI = ContextMetaData.ABI + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data -// Context is an auto generated Go binding around an Ethereum contract. -type Context struct { - ContextCaller // Read-only binding to the contract - ContextTransactor // Write-only binding to the contract - ContextFilterer // Log filterer for contract events -} - -// ContextCaller is an auto generated read-only Go binding around an Ethereum contract. -type ContextCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ContextTransactor is an auto generated write-only Go binding around an Ethereum contract. -type ContextTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration } -// ContextFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type ContextFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AdminFeeRateUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(AdminFeeRateUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true -// ContextSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type ContextSession struct { - Contract *Context // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(AdminFeeRateUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true -// ContextCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type ContextCallerSession struct { - Contract *ContextCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } } -// ContextTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type ContextTransactorSession struct { - Contract *ContextTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +// Error returns any retrieval or parsing error occurred during filtering. +func (it *AdminFeeRateUpdatedIterator) Error() error { + return it.fail } -// ContextRaw is an auto generated low-level Go binding around an Ethereum contract. -type ContextRaw struct { - Contract *Context // Generic contract binding to access the raw methods on +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AdminFeeRateUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil } -// ContextCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type ContextCallerRaw struct { - Contract *ContextCaller // Generic read-only contract binding to access the raw methods on +// AdminFeeRateUpdated represents a FeeRateUpdated event raised by the Admin contract. +type AdminFeeRateUpdated struct { + OldFeeRate *big.Int + NewFeeRate *big.Int + Raw types.Log // Blockchain specific contextual infos } -// ContextTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type ContextTransactorRaw struct { - Contract *ContextTransactor // Generic write-only contract binding to access the raw methods on -} +// FilterFeeRateUpdated is a free log retrieval operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_Admin *AdminFilterer) FilterFeeRateUpdated(opts *bind.FilterOpts) (*AdminFeeRateUpdatedIterator, error) { -// NewContext creates a new instance of Context, bound to a specific deployed contract. -func NewContext(address common.Address, backend bind.ContractBackend) (*Context, error) { - contract, err := bindContext(address, backend, backend, backend) + logs, sub, err := _Admin.contract.FilterLogs(opts, "FeeRateUpdated") if err != nil { return nil, err } - return &Context{ContextCaller: ContextCaller{contract: contract}, ContextTransactor: ContextTransactor{contract: contract}, ContextFilterer: ContextFilterer{contract: contract}}, nil + return &AdminFeeRateUpdatedIterator{contract: _Admin.contract, event: "FeeRateUpdated", logs: logs, sub: sub}, nil } -// NewContextCaller creates a new read-only instance of Context, bound to a specific deployed contract. -func NewContextCaller(address common.Address, caller bind.ContractCaller) (*ContextCaller, error) { - contract, err := bindContext(address, caller, nil, nil) +// WatchFeeRateUpdated is a free log subscription operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_Admin *AdminFilterer) WatchFeeRateUpdated(opts *bind.WatchOpts, sink chan<- *AdminFeeRateUpdated) (event.Subscription, error) { + + logs, sub, err := _Admin.contract.WatchLogs(opts, "FeeRateUpdated") if err != nil { return nil, err } - return &ContextCaller{contract: contract}, nil + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(AdminFeeRateUpdated) + if err := _Admin.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil } -// NewContextTransactor creates a new write-only instance of Context, bound to a specific deployed contract. -func NewContextTransactor(address common.Address, transactor bind.ContractTransactor) (*ContextTransactor, error) { - contract, err := bindContext(address, nil, transactor, nil) - if err != nil { +// ParseFeeRateUpdated is a log parse operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_Admin *AdminFilterer) ParseFeeRateUpdated(log types.Log) (*AdminFeeRateUpdated, error) { + event := new(AdminFeeRateUpdated) + if err := _Admin.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { return nil, err } - return &ContextTransactor{contract: contract}, nil + event.Raw = log + return event, nil } -// NewContextFilterer creates a new log filterer instance of Context, bound to a specific deployed contract. -func NewContextFilterer(address common.Address, filterer bind.ContractFilterer) (*ContextFilterer, error) { - contract, err := bindContext(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &ContextFilterer{contract: contract}, nil +// AdminFeesSweptIterator is returned from FilterFeesSwept and is used to iterate over the raw logs and unpacked data for FeesSwept events raised by the Admin contract. +type AdminFeesSweptIterator struct { + Event *AdminFeesSwept // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration } -// bindContext binds a generic wrapper to an already deployed contract. -func bindContext(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := ContextMetaData.GetAbi() - if err != nil { - return nil, err +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AdminFeesSweptIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(AdminFeesSwept) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Context *ContextRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Context.Contract.ContextCaller.contract.Call(opts, result, method, params...) -} + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(AdminFeesSwept) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Context *ContextRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Context.Contract.ContextTransactor.contract.Transfer(opts) + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } } -// Transact invokes the (paid) contract method with params as input values. -func (_Context *ContextRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Context.Contract.ContextTransactor.contract.Transact(opts, method, params...) +// Error returns any retrieval or parsing error occurred during filtering. +func (it *AdminFeesSweptIterator) Error() error { + return it.fail } -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Context *ContextCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Context.Contract.contract.Call(opts, result, method, params...) +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AdminFeesSweptIterator) Close() error { + it.sub.Unsubscribe() + return nil } -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Context *ContextTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Context.Contract.contract.Transfer(opts) +// AdminFeesSwept represents a FeesSwept event raised by the Admin contract. +type AdminFeesSwept struct { + Token common.Address + Recipient common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// Transact invokes the (paid) contract method with params as input values. -func (_Context *ContextTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Context.Contract.contract.Transact(opts, method, params...) -} +// FilterFeesSwept is a free log retrieval operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_Admin *AdminFilterer) FilterFeesSwept(opts *bind.FilterOpts) (*AdminFeesSweptIterator, error) { -// ERC165MetaData contains all meta data concerning the ERC165 contract. -var ERC165MetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Sigs: map[string]string{ - "01ffc9a7": "supportsInterface(bytes4)", - }, + logs, sub, err := _Admin.contract.FilterLogs(opts, "FeesSwept") + if err != nil { + return nil, err + } + return &AdminFeesSweptIterator{contract: _Admin.contract, event: "FeesSwept", logs: logs, sub: sub}, nil } -// ERC165ABI is the input ABI used to generate the binding from. -// Deprecated: Use ERC165MetaData.ABI instead. -var ERC165ABI = ERC165MetaData.ABI +// WatchFeesSwept is a free log subscription operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_Admin *AdminFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink chan<- *AdminFeesSwept) (event.Subscription, error) { -// Deprecated: Use ERC165MetaData.Sigs instead. -// ERC165FuncSigs maps the 4-byte function signature to its string representation. -var ERC165FuncSigs = ERC165MetaData.Sigs + logs, sub, err := _Admin.contract.WatchLogs(opts, "FeesSwept") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(AdminFeesSwept) + if err := _Admin.contract.UnpackLog(event, "FeesSwept", log); err != nil { + return err + } + event.Raw = log -// ERC165 is an auto generated Go binding around an Ethereum contract. -type ERC165 struct { - ERC165Caller // Read-only binding to the contract - ERC165Transactor // Write-only binding to the contract - ERC165Filterer // Log filterer for contract events + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil } -// ERC165Caller is an auto generated read-only Go binding around an Ethereum contract. -type ERC165Caller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls +// ParseFeesSwept is a log parse operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_Admin *AdminFilterer) ParseFeesSwept(log types.Log) (*AdminFeesSwept, error) { + event := new(AdminFeesSwept) + if err := _Admin.contract.UnpackLog(event, "FeesSwept", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil } -// ERC165Transactor is an auto generated write-only Go binding around an Ethereum contract. -type ERC165Transactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} +// AdminRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the Admin contract. +type AdminRoleAdminChangedIterator struct { + Event *AdminRoleAdminChanged // Event containing the contract specifics and raw log -// ERC165Filterer is an auto generated log filtering Go binding around an Ethereum contract events. -type ERC165Filterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data -// ERC165Session is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type ERC165Session struct { - Contract *ERC165 // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration } -// ERC165CallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type ERC165CallerSession struct { - Contract *ERC165Caller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AdminRoleAdminChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(AdminRoleAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true -// ERC165TransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type ERC165TransactorSession struct { - Contract *ERC165Transactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(AdminRoleAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true -// ERC165Raw is an auto generated low-level Go binding around an Ethereum contract. -type ERC165Raw struct { - Contract *ERC165 // Generic contract binding to access the raw methods on + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } } -// ERC165CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type ERC165CallerRaw struct { - Contract *ERC165Caller // Generic read-only contract binding to access the raw methods on +// Error returns any retrieval or parsing error occurred during filtering. +func (it *AdminRoleAdminChangedIterator) Error() error { + return it.fail } -// ERC165TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type ERC165TransactorRaw struct { - Contract *ERC165Transactor // Generic write-only contract binding to access the raw methods on +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AdminRoleAdminChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil } -// NewERC165 creates a new instance of ERC165, bound to a specific deployed contract. -func NewERC165(address common.Address, backend bind.ContractBackend) (*ERC165, error) { - contract, err := bindERC165(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &ERC165{ERC165Caller: ERC165Caller{contract: contract}, ERC165Transactor: ERC165Transactor{contract: contract}, ERC165Filterer: ERC165Filterer{contract: contract}}, nil +// AdminRoleAdminChanged represents a RoleAdminChanged event raised by the Admin contract. +type AdminRoleAdminChanged struct { + Role [32]byte + PreviousAdminRole [32]byte + NewAdminRole [32]byte + Raw types.Log // Blockchain specific contextual infos } -// NewERC165Caller creates a new read-only instance of ERC165, bound to a specific deployed contract. -func NewERC165Caller(address common.Address, caller bind.ContractCaller) (*ERC165Caller, error) { - contract, err := bindERC165(address, caller, nil, nil) - if err != nil { - return nil, err +// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_Admin *AdminFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*AdminRoleAdminChangedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) } - return &ERC165Caller{contract: contract}, nil -} -// NewERC165Transactor creates a new write-only instance of ERC165, bound to a specific deployed contract. -func NewERC165Transactor(address common.Address, transactor bind.ContractTransactor) (*ERC165Transactor, error) { - contract, err := bindERC165(address, nil, transactor, nil) + logs, sub, err := _Admin.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { return nil, err } - return &ERC165Transactor{contract: contract}, nil + return &AdminRoleAdminChangedIterator{contract: _Admin.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil } -// NewERC165Filterer creates a new log filterer instance of ERC165, bound to a specific deployed contract. -func NewERC165Filterer(address common.Address, filterer bind.ContractFilterer) (*ERC165Filterer, error) { - contract, err := bindERC165(address, nil, nil, filterer) - if err != nil { - return nil, err +// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_Admin *AdminFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *AdminRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) } - return &ERC165Filterer{contract: contract}, nil -} -// bindERC165 binds a generic wrapper to an already deployed contract. -func bindERC165(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := ERC165MetaData.GetAbi() + logs, sub, err := _Admin.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { return nil, err } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_ERC165 *ERC165Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _ERC165.Contract.ERC165Caller.contract.Call(opts, result, method, params...) -} + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(AdminRoleAdminChanged) + if err := _Admin.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { + return err + } + event.Raw = log -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_ERC165 *ERC165Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _ERC165.Contract.ERC165Transactor.contract.Transfer(opts) + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil } -// Transact invokes the (paid) contract method with params as input values. -func (_ERC165 *ERC165Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _ERC165.Contract.ERC165Transactor.contract.Transact(opts, method, params...) +// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_Admin *AdminFilterer) ParseRoleAdminChanged(log types.Log) (*AdminRoleAdminChanged, error) { + event := new(AdminRoleAdminChanged) + if err := _Admin.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil } -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_ERC165 *ERC165CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _ERC165.Contract.contract.Call(opts, result, method, params...) -} +// AdminRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the Admin contract. +type AdminRoleGrantedIterator struct { + Event *AdminRoleGranted // Event containing the contract specifics and raw log -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_ERC165 *ERC165TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _ERC165.Contract.contract.Transfer(opts) -} + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data -// Transact invokes the (paid) contract method with params as input values. -func (_ERC165 *ERC165TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _ERC165.Contract.contract.Transact(opts, method, params...) + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration } -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_ERC165 *ERC165Caller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { - var out []interface{} - err := _ERC165.contract.Call(opts, &out, "supportsInterface", interfaceId) - - if err != nil { - return *new(bool), err +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AdminRoleGrantedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(AdminRoleGranted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(AdminRoleGranted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } } -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_ERC165 *ERC165Session) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _ERC165.Contract.SupportsInterface(&_ERC165.CallOpts, interfaceId) +// Error returns any retrieval or parsing error occurred during filtering. +func (it *AdminRoleGrantedIterator) Error() error { + return it.fail } -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_ERC165 *ERC165CallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _ERC165.Contract.SupportsInterface(&_ERC165.CallOpts, interfaceId) +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AdminRoleGrantedIterator) Close() error { + it.sub.Unsubscribe() + return nil } -// FastBridgeMetaData contains all meta data concerning the FastBridge contract. -var FastBridgeMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineNotExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineTooShort\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputePeriodNotPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputePeriodPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MsgValueIncorrect\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SenderIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StatusIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenNotContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransactionRelayed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositRefunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"BridgeProofDisputed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"transactionHash\",\"type\":\"bytes32\"}],\"name\":\"BridgeProofProvided\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"BridgeRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"}],\"name\":\"BridgeRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DISPUTE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_DEADLINE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROVE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"addGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"addGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"addRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"structIFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"bridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeProofs\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"timestamp\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeRelays\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeStatuses\",\"outputs\":[{\"internalType\":\"enumFastBridge.BridgeStatus\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"canClaim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"dispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"getBridgeTransaction\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originSender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destRecipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originFeeAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"internalType\":\"structIFastBridge.BridgeTransaction\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"destTxHash\",\"type\":\"bytes32\"}],\"name\":\"prove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"refund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"removeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"removeGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"removeRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Sigs: map[string]string{ - "a217fddf": "DEFAULT_ADMIN_ROLE()", - "a5bbe22b": "DISPUTE_PERIOD()", - "bf333f2c": "FEE_BPS()", - "0f5f6ed7": "FEE_RATE_MAX()", - "ccc57490": "GOVERNOR_ROLE()", - "03ed0ee5": "GUARD_ROLE()", - "820688d5": "MIN_DEADLINE_PERIOD()", - "d3cbc760": "PROVE_PERIOD()", - "926d7d7f": "RELAYER_ROLE()", - "3c4a25d0": "addGovernor(address)", - "6913a63c": "addGuard(address)", - "dd39f00d": "addRelayer(address)", - "45851694": "bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))", - "91ad5039": "bridgeProofs(bytes32)", - "8379a24f": "bridgeRelays(bytes32)", - "051287bc": "bridgeStatuses(bytes32)", - "aa9641ab": "canClaim(bytes32,address)", - "e00a83e0": "chainGasAmount()", - "41fcb612": "claim(bytes,address)", - "a3ec191a": "deployBlock()", - "add98c70": "dispute(bytes32)", - "ac11fb1a": "getBridgeTransaction(bytes)", - "248a9ca3": "getRoleAdmin(bytes32)", - "2f2ff15d": "grantRole(bytes32,address)", - "91d14854": "hasRole(bytes32,address)", - "affed0e0": "nonce()", - "58f85880": "protocolFeeRate()", - "dcf844a7": "protocolFees(address)", - "886d36ff": "prove(bytes,bytes32)", - "5eb7d946": "refund(bytes)", - "8f0d6f17": "relay(bytes)", - "eecdac88": "removeGovernor(address)", - "b6235016": "removeGuard(address)", - "60f0a5ac": "removeRelayer(address)", - "36568abe": "renounceRole(bytes32,address)", - "d547741f": "revokeRole(bytes32,address)", - "b250fe6b": "setChainGasAmount(uint256)", - "b13aa2d6": "setProtocolFeeRate(uint256)", - "01ffc9a7": "supportsInterface(bytes4)", - "06f333f2": "sweepProtocolFees(address,address)", - }, - Bin: "0x60a06040523480156200001157600080fd5b5060405162003105380380620031058339810160408190526200003491620000fe565b80620000426000826200004f565b5050436080525062000130565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16620000f4576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620000ab3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001620000f8565b5060005b92915050565b6000602082840312156200011157600080fd5b81516001600160a01b03811681146200012957600080fd5b9392505050565b608051612fb96200014c600039600061067f0152612fb96000f3fe6080604052600436106102bb5760003560e01c806391d148541161016e578063b250fe6b116100cb578063d547741f1161007f578063dd39f00d11610064578063dd39f00d14610832578063e00a83e014610852578063eecdac881461086857600080fd5b8063d547741f146107e5578063dcf844a71461080557600080fd5b8063bf333f2c116100b0578063bf333f2c14610784578063ccc574901461079b578063d3cbc760146107cf57600080fd5b8063b250fe6b14610744578063b62350161461076457600080fd5b8063aa9641ab11610122578063add98c7011610107578063add98c70146106ee578063affed0e01461070e578063b13aa2d61461072457600080fd5b8063aa9641ab146106a1578063ac11fb1a146106c157600080fd5b8063a217fddf11610153578063a217fddf14610658578063a3ec191a1461066d578063a5bbe22b146104e557600080fd5b806391d14854146105e0578063926d7d7f1461062457600080fd5b8063458516941161021c578063820688d5116101d0578063886d36ff116101b5578063886d36ff1461052b5780638f0d6f171461054b57806391ad50391461055e57600080fd5b8063820688d5146104e55780638379a24f146104fb57600080fd5b80635eb7d946116102015780635eb7d9461461048557806360f0a5ac146104a55780636913a63c146104c557600080fd5b8063458516941461045c57806358f858801461046f57600080fd5b8063248a9ca31161027357806336568abe1161025857806336568abe146103fc5780633c4a25d01461041c57806341fcb6121461043c57600080fd5b8063248a9ca3146103ac5780632f2ff15d146103dc57600080fd5b8063051287bc116102a4578063051287bc1461033757806306f333f2146103745780630f5f6ed71461039657600080fd5b806301ffc9a7146102c057806303ed0ee5146102f5575b600080fd5b3480156102cc57600080fd5b506102e06102db366004612796565b610888565b60405190151581526020015b60405180910390f35b34801561030157600080fd5b506103297f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b6040519081526020016102ec565b34801561034357600080fd5b506103676103523660046127d8565b60046020526000908152604090205460ff1681565b6040516102ec9190612820565b34801561038057600080fd5b5061039461038f366004612886565b610921565b005b3480156103a257600080fd5b5061032961271081565b3480156103b857600080fd5b506103296103c73660046127d8565b60009081526020819052604090206001015490565b3480156103e857600080fd5b506103946103f73660046128bf565b610a59565b34801561040857600080fd5b506103946104173660046128bf565b610a84565b34801561042857600080fd5b506103946104373660046128e4565b610ad5565b34801561044857600080fd5b50610394610457366004612a29565b610b7b565b61039461046a366004612aa6565b610e23565b34801561047b57600080fd5b5061032960015481565b34801561049157600080fd5b506103946104a0366004612b49565b611131565b3480156104b157600080fd5b506103946104c03660046128e4565b611294565b3480156104d157600080fd5b506103946104e03660046128e4565b611333565b3480156104f157600080fd5b5061032961070881565b34801561050757600080fd5b506102e06105163660046127d8565b60066020526000908152604090205460ff1681565b34801561053757600080fd5b50610394610546366004612b86565b6113d2565b610394610559366004612b49565b6115ce565b34801561056a57600080fd5b506105b46105793660046127d8565b6005602052600090815260409020546bffffffffffffffffffffffff8116906c0100000000000000000000000090046001600160a01b031682565b604080516bffffffffffffffffffffffff90931683526001600160a01b039091166020830152016102ec565b3480156105ec57600080fd5b506102e06105fb3660046128bf565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561063057600080fd5b506103297fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b34801561066457600080fd5b50610329600081565b34801561067957600080fd5b506103297f000000000000000000000000000000000000000000000000000000000000000081565b3480156106ad57600080fd5b506102e06106bc3660046128bf565b611883565b3480156106cd57600080fd5b506106e16106dc366004612b49565b611988565b6040516102ec9190612bcb565b3480156106fa57600080fd5b506103946107093660046127d8565b6119fb565b34801561071a57600080fd5b5061032960075481565b34801561073057600080fd5b5061039461073f3660046127d8565b611bd3565b34801561075057600080fd5b5061039461075f3660046127d8565b611d1d565b34801561077057600080fd5b5061039461077f3660046128e4565b611df3565b34801561079057600080fd5b50610329620f424081565b3480156107a757600080fd5b506103297f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b3480156107db57600080fd5b50610329610e1081565b3480156107f157600080fd5b506103946108003660046128bf565b611e92565b34801561081157600080fd5b506103296108203660046128e4565b60026020526000908152604090205481565b34801561083e57600080fd5b5061039461084d3660046128e4565b611eb7565b34801561085e57600080fd5b5061032960035481565b34801561087457600080fd5b506103946108833660046128e4565b611f56565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061091b57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff166109be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064015b60405180910390fd5b6001600160a01b038216600090815260026020526040812054908190036109e457505050565b6001600160a01b038316600081815260026020526040812055610a08908383611ff5565b604080516001600160a01b038086168252841660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b5050565b600082815260208190526040902060010154610a7481612118565b610a7e8383612125565b50505050565b6001600160a01b0381163314610ac6576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ad082826121cf565b505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610b1057600080fd5b610b3a7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5582612125565b506040516001600160a01b03821681527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5906020015b60405180910390a150565b3360009081527ffaf93c3d007e112089dc8351e013e6685ef67703975d0224b26fc45941d4f1f5602052604090205460ff16610c13576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616c6c6572206973206e6f7420612072656c6179657200000000000000000060448201526064016109b5565b815160208301206000610c2584611988565b9050600260008381526004602081905260409091205460ff1690811115610c4e57610c4e6127f1565b14610c85576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040918290208251808401909352546bffffffffffffffffffffffff811683526c0100000000000000000000000090046001600160a01b03169082018190523314610d08576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611610d55576040517f1992d0bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600460205260409020805460ff1916600317905561010082015115610db15761010082015160808301516001600160a01b031660009081526002602052604081208054909190610dab908490612ce0565b90915550505b608082015160c0830151610dcf6001600160a01b0383168783611ff5565b604080516001600160a01b03848116825260208201849052881691339188917f582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac67891015b60405180910390a450505050505050565b46816000015163ffffffff1603610e66576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a08101511580610e79575060c0810151155b15610eb0576040517fe38820c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608101516001600160a01b03161580610ed5575060808101516001600160a01b0316155b15610f0c576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f1861070842612ce0565b8161010001511015610f56576040517f04b7fcc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610f6b3083606001518460a00151612252565b90506000806001541115610f9857620f424060015483610f8b9190612cf3565b610f959190612d0a565b90505b610fa28183612d45565b915060006040518061018001604052804663ffffffff168152602001856000015163ffffffff16815260200185602001516001600160a01b0316815260200185604001516001600160a01b0316815260200185606001516001600160a01b0316815260200185608001516001600160a01b031681526020018481526020018560c0015181526020018381526020018560e001511515815260200185610100015181526020016007600081548092919061105a90612d58565b9091555090526040516110709190602001612bcb565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152828252805160208083019190912060008181526004835293909320805460ff191660011790558701518751606089015160808a015160c08b015160e08c015195985095966001600160a01b039094169587957f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a95611122958b959094909390928e92612db4565b60405180910390a35050505050565b80516020820120600061114383611988565b9050610e108161014001516111589190612ce0565b4211611190576040517fe15ff9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008381526004602081905260409091205460ff16908111156111b7576111b76127f1565b146111ee576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600460208190526040909120805460ff191660018302179055506040810151608082015161010083015160c084015160009161122e91612ce0565b90506112446001600160a01b0383168483611ff5565b604080516001600160a01b0384811682526020820184905285169187917fb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958910160405180910390a3505050505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166112cf57600080fd5b6112f97fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4826121cf565b506040516001600160a01b03821681527f10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b90602001610b70565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661136e57600080fd5b6113987f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d82612125565b506040516001600160a01b03821681527f93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f5990602001610b70565b3360009081527ffaf93c3d007e112089dc8351e013e6685ef67703975d0224b26fc45941d4f1f5602052604090205460ff1661146a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616c6c6572206973206e6f7420612072656c6179657200000000000000000060448201526064016109b5565b81516020830120600061147c84611988565b9050610e108161014001516114919190612ce0565b4211156114ca576040517f559895a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008381526004602081905260409091205460ff16908111156114f1576114f16127f1565b14611528576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526004602090815260408083208054600260ff19909116179055805180820182526bffffffffffffffffffffffff4281168252338285018181528887526005865295849020925195516001600160a01b03166c0100000000000000000000000002959091169490941790555185815284917f4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4910160405180910390a350505050565b3360009081527ffaf93c3d007e112089dc8351e013e6685ef67703975d0224b26fc45941d4f1f5602052604090205460ff16611666576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616c6c6572206973206e6f7420612072656c6179657200000000000000000060448201526064016109b5565b80516020820120600061167883611988565b90504663ffffffff16816020015163ffffffff16146116c3576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806101400151421115611702576040517f559895a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205460ff161561174b576040517fbef7bb7d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660205260409020805460ff19166001179055606081015160a082015160e08301516003546101208501516117945750600061178e848484612252565b50611805565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b038416016117d85761178e84846117d38486612ce0565b612252565b6117e3848484612252565b506118038473eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee83612252565b505b845160808087015160a08089015160c0808b015160e08c01516040805163ffffffff90991689526001600160a01b0396871660208a0152938616938801939093526060870152938501528301849052861691339189917ff8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c9101610e12565b6000600260008481526004602081905260409091205460ff16908111156118ac576118ac6127f1565b146118e3576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600560209081526040918290208251808401909352546bffffffffffffffffffffffff811683526001600160a01b036c010000000000000000000000009091048116918301829052841614611969576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611949350505050565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201528251909161091b9184018101908401612e65565b3360009081527f92bf2f06c618f6add65571bf52eb90d22c9b52fd65028daa87260b82998b30bd602052604090205460ff16611a93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f43616c6c6572206973206e6f742061206775617264000000000000000000000060448201526064016109b5565b600260008281526004602081905260409091205460ff1690811115611aba57611aba6127f1565b14611af1576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600560209081526040918290208251808401909352546bffffffffffffffffffffffff8082168085526c010000000000000000000000009092046001600160a01b03169390920192909252610708914203161115611b80576040517f3e908aac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460209081526040808320805460ff19166001179055600590915280822082905551339183917f0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad49190a350565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16611c6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064016109b5565b612710811115611cd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064016109b5565b600180549082905560408051828152602081018490527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a15050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16611db5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064016109b5565b600380549082905560408051828152602081018490527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa9101611d11565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611e2e57600080fd5b611e587f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d826121cf565b506040516001600160a01b03821681527f59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d04890602001610b70565b600082815260208190526040902060010154611ead81612118565b610a7e83836121cf565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611ef257600080fd5b611f1c7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc482612125565b506040516001600160a01b03821681527f03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c590602001610b70565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611f9157600080fd5b611fbb7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55826121cf565b506040516001600160a01b03821681527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b90602001610b70565b306001600160a01b0383160361200a57505050565b8060000361201757505050565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03841601612104576000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612094576040519150601f19603f3d011682016040523d82523d6000602084013e612099565b606091505b5050905080610a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c65640000000000000000000000000060448201526064016109b5565b610ad06001600160a01b0384168383612422565b6121228133612496565b50565b6000828152602081815260408083206001600160a01b038516845290915281205460ff166121c7576000838152602081815260408083206001600160a01b03861684529091529020805460ff1916600117905561217f3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161091b565b50600061091b565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16156121c7576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161091b565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146123bb5761228a836001600160a01b0316612502565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528416906370a0823190602401602060405180830381865afa1580156122e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061230d9190612f31565b90506123246001600160a01b0384163386856125a8565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528291908516906370a0823190602401602060405180830381865afa158015612386573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123aa9190612f31565b6123b49190612d45565b905061241b565b3482146123f4576040517f81de0bf300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0384163014612418576124186001600160a01b0384168584611ff5565b50345b9392505050565b6040516001600160a01b03838116602483015260448201839052610ad091859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506125e1565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610a55576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602481018390526044016109b5565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03821601612564576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03163b600003612122576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038481166024830152838116604483015260648201839052610a7e9186918216906323b872dd9060840161244f565b60006125f66001600160a01b0384168361265d565b9050805160001415801561261b5750808060200190518101906126199190612f4a565b155b15610ad0576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024016109b5565b606061241b8383600084600080856001600160a01b031684866040516126839190612f67565b60006040518083038185875af1925050503d80600081146126c0576040519150601f19603f3d011682016040523d82523d6000602084013e6126c5565b606091505b50915091506126d58683836126df565b9695505050505050565b6060826126f4576126ef82612754565b61241b565b815115801561270b57506001600160a01b0384163b155b1561274d576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016109b5565b508061241b565b8051156127645780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602082840312156127a857600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461241b57600080fd5b6000602082840312156127ea57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016005831061285b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6001600160a01b038116811461212257600080fd5b803561288181612861565b919050565b6000806040838503121561289957600080fd5b82356128a481612861565b915060208301356128b481612861565b809150509250929050565b600080604083850312156128d257600080fd5b8235915060208301356128b481612861565b6000602082840312156128f657600080fd5b813561241b81612861565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171561295457612954612901565b60405290565b604051610180810167ffffffffffffffff8111828210171561295457612954612901565b600082601f83011261298f57600080fd5b813567ffffffffffffffff808211156129aa576129aa612901565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156129f0576129f0612901565b81604052838152866020858801011115612a0957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215612a3c57600080fd5b823567ffffffffffffffff811115612a5357600080fd5b612a5f8582860161297e565b92505060208301356128b481612861565b63ffffffff8116811461212257600080fd5b803561288181612a70565b801515811461212257600080fd5b803561288181612a8d565b60006101208284031215612ab957600080fd5b612ac1612930565b612aca83612a82565b8152612ad860208401612876565b6020820152612ae960408401612876565b6040820152612afa60608401612876565b6060820152612b0b60808401612876565b608082015260a083013560a082015260c083013560c0820152612b3060e08401612a9b565b60e0820152610100928301359281019290925250919050565b600060208284031215612b5b57600080fd5b813567ffffffffffffffff811115612b7257600080fd5b612b7e8482850161297e565b949350505050565b60008060408385031215612b9957600080fd5b823567ffffffffffffffff811115612bb057600080fd5b612bbc8582860161297e565b95602094909401359450505050565b815163ffffffff16815261018081016020830151612bf1602084018263ffffffff169052565b506040830151612c0c60408401826001600160a01b03169052565b506060830151612c2760608401826001600160a01b03169052565b506080830151612c4260808401826001600160a01b03169052565b5060a0830151612c5d60a08401826001600160a01b03169052565b5060c083015160c083015260e083015160e083015261010080840151818401525061012080840151612c928285018215159052565b5050610140838101519083015261016092830151929091019190915290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561091b5761091b612cb1565b808202811582820484141761091b5761091b612cb1565b600082612d40577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561091b5761091b612cb1565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612d8957612d89612cb1565b5060010190565b60005b83811015612dab578181015183820152602001612d93565b50506000910152565b60e08152600088518060e0840152610100612dd58282860160208e01612d90565b63ffffffff9990991660208401526001600160a01b039788166040840152959096166060820152608081019390935260a0830191909152151560c0820152601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190910192915050565b805161288181612a70565b805161288181612861565b805161288181612a8d565b60006101808284031215612e7857600080fd5b612e8061295a565b612e8983612e44565b8152612e9760208401612e44565b6020820152612ea860408401612e4f565b6040820152612eb960608401612e4f565b6060820152612eca60808401612e4f565b6080820152612edb60a08401612e4f565b60a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120612f0e818501612e5a565b908201526101408381015190820152610160928301519281019290925250919050565b600060208284031215612f4357600080fd5b5051919050565b600060208284031215612f5c57600080fd5b815161241b81612a8d565b60008251612f79818460208701612d90565b919091019291505056fea2646970667358221220cfbaf6e83822ac30c6a2a632f0f3210ee79769ee0c58ec096e96669f3b90e1c064736f6c63430008140033", +// AdminRoleGranted represents a RoleGranted event raised by the Admin contract. +type AdminRoleGranted struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos } -// FastBridgeABI is the input ABI used to generate the binding from. -// Deprecated: Use FastBridgeMetaData.ABI instead. -var FastBridgeABI = FastBridgeMetaData.ABI - -// Deprecated: Use FastBridgeMetaData.Sigs instead. -// FastBridgeFuncSigs maps the 4-byte function signature to its string representation. -var FastBridgeFuncSigs = FastBridgeMetaData.Sigs - -// FastBridgeBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use FastBridgeMetaData.Bin instead. -var FastBridgeBin = FastBridgeMetaData.Bin +// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_Admin *AdminFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*AdminRoleGrantedIterator, error) { -// DeployFastBridge deploys a new Ethereum contract, binding an instance of FastBridge to it. -func DeployFastBridge(auth *bind.TransactOpts, backend bind.ContractBackend, _owner common.Address) (common.Address, *types.Transaction, *FastBridge, error) { - parsed, err := FastBridgeMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(FastBridgeBin), backend, _owner) + logs, sub, err := _Admin.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) if err != nil { - return common.Address{}, nil, nil, err + return nil, err } - return address, tx, &FastBridge{FastBridgeCaller: FastBridgeCaller{contract: contract}, FastBridgeTransactor: FastBridgeTransactor{contract: contract}, FastBridgeFilterer: FastBridgeFilterer{contract: contract}}, nil -} - -// FastBridge is an auto generated Go binding around an Ethereum contract. -type FastBridge struct { - FastBridgeCaller // Read-only binding to the contract - FastBridgeTransactor // Write-only binding to the contract - FastBridgeFilterer // Log filterer for contract events + return &AdminRoleGrantedIterator{contract: _Admin.contract, event: "RoleGranted", logs: logs, sub: sub}, nil } -// FastBridgeCaller is an auto generated read-only Go binding around an Ethereum contract. -type FastBridgeCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} +// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_Admin *AdminFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *AdminRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { -// FastBridgeTransactor is an auto generated write-only Go binding around an Ethereum contract. -type FastBridgeTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } -// FastBridgeFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type FastBridgeFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} + logs, sub, err := _Admin.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(AdminRoleGranted) + if err := _Admin.contract.UnpackLog(event, "RoleGranted", log); err != nil { + return err + } + event.Raw = log -// FastBridgeSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type FastBridgeSession struct { - Contract *FastBridge // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil } -// FastBridgeCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type FastBridgeCallerSession struct { - Contract *FastBridgeCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session +// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_Admin *AdminFilterer) ParseRoleGranted(log types.Log) (*AdminRoleGranted, error) { + event := new(AdminRoleGranted) + if err := _Admin.contract.UnpackLog(event, "RoleGranted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil } -// FastBridgeTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type FastBridgeTransactorSession struct { - Contract *FastBridgeTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +// AdminRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the Admin contract. +type AdminRoleRevokedIterator struct { + Event *AdminRoleRevoked // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration } -// FastBridgeRaw is an auto generated low-level Go binding around an Ethereum contract. -type FastBridgeRaw struct { - Contract *FastBridge // Generic contract binding to access the raw methods on +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AdminRoleRevokedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(AdminRoleRevoked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(AdminRoleRevoked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } } -// FastBridgeCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type FastBridgeCallerRaw struct { - Contract *FastBridgeCaller // Generic read-only contract binding to access the raw methods on +// Error returns any retrieval or parsing error occurred during filtering. +func (it *AdminRoleRevokedIterator) Error() error { + return it.fail } -// FastBridgeTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type FastBridgeTransactorRaw struct { - Contract *FastBridgeTransactor // Generic write-only contract binding to access the raw methods on +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AdminRoleRevokedIterator) Close() error { + it.sub.Unsubscribe() + return nil } -// NewFastBridge creates a new instance of FastBridge, bound to a specific deployed contract. -func NewFastBridge(address common.Address, backend bind.ContractBackend) (*FastBridge, error) { - contract, err := bindFastBridge(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &FastBridge{FastBridgeCaller: FastBridgeCaller{contract: contract}, FastBridgeTransactor: FastBridgeTransactor{contract: contract}, FastBridgeFilterer: FastBridgeFilterer{contract: contract}}, nil +// AdminRoleRevoked represents a RoleRevoked event raised by the Admin contract. +type AdminRoleRevoked struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos } -// NewFastBridgeCaller creates a new read-only instance of FastBridge, bound to a specific deployed contract. -func NewFastBridgeCaller(address common.Address, caller bind.ContractCaller) (*FastBridgeCaller, error) { - contract, err := bindFastBridge(address, caller, nil, nil) - if err != nil { - return nil, err +// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_Admin *AdminFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*AdminRoleRevokedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) } - return &FastBridgeCaller{contract: contract}, nil -} -// NewFastBridgeTransactor creates a new write-only instance of FastBridge, bound to a specific deployed contract. -func NewFastBridgeTransactor(address common.Address, transactor bind.ContractTransactor) (*FastBridgeTransactor, error) { - contract, err := bindFastBridge(address, nil, transactor, nil) + logs, sub, err := _Admin.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) if err != nil { return nil, err } - return &FastBridgeTransactor{contract: contract}, nil + return &AdminRoleRevokedIterator{contract: _Admin.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil } -// NewFastBridgeFilterer creates a new log filterer instance of FastBridge, bound to a specific deployed contract. -func NewFastBridgeFilterer(address common.Address, filterer bind.ContractFilterer) (*FastBridgeFilterer, error) { - contract, err := bindFastBridge(address, nil, nil, filterer) +// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_Admin *AdminFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *AdminRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _Admin.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) if err != nil { return nil, err } - return &FastBridgeFilterer{contract: contract}, nil + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(AdminRoleRevoked) + if err := _Admin.contract.UnpackLog(event, "RoleRevoked", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil } -// bindFastBridge binds a generic wrapper to an already deployed contract. -func bindFastBridge(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := FastBridgeMetaData.GetAbi() - if err != nil { +// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_Admin *AdminFilterer) ParseRoleRevoked(log types.Log) (*AdminRoleRevoked, error) { + event := new(AdminRoleRevoked) + if err := _Admin.contract.UnpackLog(event, "RoleRevoked", log); err != nil { return nil, err } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil + event.Raw = log + return event, nil } -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_FastBridge *FastBridgeRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _FastBridge.Contract.FastBridgeCaller.contract.Call(opts, result, method, params...) +// ContextMetaData contains all meta data concerning the Context contract. +var ContextMetaData = &bind.MetaData{ + ABI: "[]", } -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_FastBridge *FastBridgeRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _FastBridge.Contract.FastBridgeTransactor.contract.Transfer(opts) -} +// ContextABI is the input ABI used to generate the binding from. +// Deprecated: Use ContextMetaData.ABI instead. +var ContextABI = ContextMetaData.ABI -// Transact invokes the (paid) contract method with params as input values. -func (_FastBridge *FastBridgeRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _FastBridge.Contract.FastBridgeTransactor.contract.Transact(opts, method, params...) +// Context is an auto generated Go binding around an Ethereum contract. +type Context struct { + ContextCaller // Read-only binding to the contract + ContextTransactor // Write-only binding to the contract + ContextFilterer // Log filterer for contract events } -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_FastBridge *FastBridgeCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _FastBridge.Contract.contract.Call(opts, result, method, params...) +// ContextCaller is an auto generated read-only Go binding around an Ethereum contract. +type ContextCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_FastBridge *FastBridgeTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _FastBridge.Contract.contract.Transfer(opts) +// ContextTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ContextTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// Transact invokes the (paid) contract method with params as input values. -func (_FastBridge *FastBridgeTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _FastBridge.Contract.contract.Transact(opts, method, params...) +// ContextFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ContextFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. -// -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) +// ContextSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ContextSession struct { + Contract *Context // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} - return out0, err +// ContextCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ContextCallerSession struct { + Contract *ContextCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} +// ContextTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ContextTransactorSession struct { + Contract *ContextTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. -// -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeSession) DEFAULTADMINROLE() ([32]byte, error) { - return _FastBridge.Contract.DEFAULTADMINROLE(&_FastBridge.CallOpts) +// ContextRaw is an auto generated low-level Go binding around an Ethereum contract. +type ContextRaw struct { + Contract *Context // Generic contract binding to access the raw methods on } -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. -// -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeCallerSession) DEFAULTADMINROLE() ([32]byte, error) { - return _FastBridge.Contract.DEFAULTADMINROLE(&_FastBridge.CallOpts) +// ContextCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ContextCallerRaw struct { + Contract *ContextCaller // Generic read-only contract binding to access the raw methods on } -// DISPUTEPERIOD is a free data retrieval call binding the contract method 0xa5bbe22b. -// -// Solidity: function DISPUTE_PERIOD() view returns(uint256) -func (_FastBridge *FastBridgeCaller) DISPUTEPERIOD(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "DISPUTE_PERIOD") +// ContextTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ContextTransactorRaw struct { + Contract *ContextTransactor // Generic write-only contract binding to access the raw methods on +} +// NewContext creates a new instance of Context, bound to a specific deployed contract. +func NewContext(address common.Address, backend bind.ContractBackend) (*Context, error) { + contract, err := bindContext(address, backend, backend, backend) if err != nil { - return *new(*big.Int), err + return nil, err } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - + return &Context{ContextCaller: ContextCaller{contract: contract}, ContextTransactor: ContextTransactor{contract: contract}, ContextFilterer: ContextFilterer{contract: contract}}, nil } -// DISPUTEPERIOD is a free data retrieval call binding the contract method 0xa5bbe22b. -// -// Solidity: function DISPUTE_PERIOD() view returns(uint256) -func (_FastBridge *FastBridgeSession) DISPUTEPERIOD() (*big.Int, error) { - return _FastBridge.Contract.DISPUTEPERIOD(&_FastBridge.CallOpts) +// NewContextCaller creates a new read-only instance of Context, bound to a specific deployed contract. +func NewContextCaller(address common.Address, caller bind.ContractCaller) (*ContextCaller, error) { + contract, err := bindContext(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ContextCaller{contract: contract}, nil } -// DISPUTEPERIOD is a free data retrieval call binding the contract method 0xa5bbe22b. -// -// Solidity: function DISPUTE_PERIOD() view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) DISPUTEPERIOD() (*big.Int, error) { - return _FastBridge.Contract.DISPUTEPERIOD(&_FastBridge.CallOpts) +// NewContextTransactor creates a new write-only instance of Context, bound to a specific deployed contract. +func NewContextTransactor(address common.Address, transactor bind.ContractTransactor) (*ContextTransactor, error) { + contract, err := bindContext(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ContextTransactor{contract: contract}, nil } -// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. -// -// Solidity: function FEE_BPS() view returns(uint256) -func (_FastBridge *FastBridgeCaller) FEEBPS(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "FEE_BPS") +// NewContextFilterer creates a new log filterer instance of Context, bound to a specific deployed contract. +func NewContextFilterer(address common.Address, filterer bind.ContractFilterer) (*ContextFilterer, error) { + contract, err := bindContext(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ContextFilterer{contract: contract}, nil +} +// bindContext binds a generic wrapper to an already deployed contract. +func bindContext(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ContextMetaData.GetAbi() if err != nil { - return *new(*big.Int), err + return nil, err } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Context *ContextRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Context.Contract.ContextCaller.contract.Call(opts, result, method, params...) +} - return out0, err +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Context *ContextRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Context.Contract.ContextTransactor.contract.Transfer(opts) +} +// Transact invokes the (paid) contract method with params as input values. +func (_Context *ContextRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Context.Contract.ContextTransactor.contract.Transact(opts, method, params...) } -// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. -// -// Solidity: function FEE_BPS() view returns(uint256) -func (_FastBridge *FastBridgeSession) FEEBPS() (*big.Int, error) { - return _FastBridge.Contract.FEEBPS(&_FastBridge.CallOpts) +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Context *ContextCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Context.Contract.contract.Call(opts, result, method, params...) } -// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. -// -// Solidity: function FEE_BPS() view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) FEEBPS() (*big.Int, error) { - return _FastBridge.Contract.FEEBPS(&_FastBridge.CallOpts) +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Context *ContextTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Context.Contract.contract.Transfer(opts) } -// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. -// -// Solidity: function FEE_RATE_MAX() view returns(uint256) -func (_FastBridge *FastBridgeCaller) FEERATEMAX(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "FEE_RATE_MAX") +// Transact invokes the (paid) contract method with params as input values. +func (_Context *ContextTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Context.Contract.contract.Transact(opts, method, params...) +} - if err != nil { - return *new(*big.Int), err - } +// ERC165MetaData contains all meta data concerning the ERC165 contract. +var ERC165MetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "01ffc9a7": "supportsInterface(bytes4)", + }, +} - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) +// ERC165ABI is the input ABI used to generate the binding from. +// Deprecated: Use ERC165MetaData.ABI instead. +var ERC165ABI = ERC165MetaData.ABI - return out0, err +// Deprecated: Use ERC165MetaData.Sigs instead. +// ERC165FuncSigs maps the 4-byte function signature to its string representation. +var ERC165FuncSigs = ERC165MetaData.Sigs +// ERC165 is an auto generated Go binding around an Ethereum contract. +type ERC165 struct { + ERC165Caller // Read-only binding to the contract + ERC165Transactor // Write-only binding to the contract + ERC165Filterer // Log filterer for contract events } -// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. -// -// Solidity: function FEE_RATE_MAX() view returns(uint256) -func (_FastBridge *FastBridgeSession) FEERATEMAX() (*big.Int, error) { - return _FastBridge.Contract.FEERATEMAX(&_FastBridge.CallOpts) +// ERC165Caller is an auto generated read-only Go binding around an Ethereum contract. +type ERC165Caller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. -// -// Solidity: function FEE_RATE_MAX() view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) FEERATEMAX() (*big.Int, error) { - return _FastBridge.Contract.FEERATEMAX(&_FastBridge.CallOpts) +// ERC165Transactor is an auto generated write-only Go binding around an Ethereum contract. +type ERC165Transactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. -// -// Solidity: function GOVERNOR_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeCaller) GOVERNORROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "GOVERNOR_ROLE") +// ERC165Filterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ERC165Filterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} - if err != nil { - return *new([32]byte), err - } +// ERC165Session is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ERC165Session struct { + Contract *ERC165 // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) +// ERC165CallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ERC165CallerSession struct { + Contract *ERC165Caller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} - return out0, err +// ERC165TransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ERC165TransactorSession struct { + Contract *ERC165Transactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} +// ERC165Raw is an auto generated low-level Go binding around an Ethereum contract. +type ERC165Raw struct { + Contract *ERC165 // Generic contract binding to access the raw methods on } -// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. -// -// Solidity: function GOVERNOR_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeSession) GOVERNORROLE() ([32]byte, error) { - return _FastBridge.Contract.GOVERNORROLE(&_FastBridge.CallOpts) +// ERC165CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ERC165CallerRaw struct { + Contract *ERC165Caller // Generic read-only contract binding to access the raw methods on } -// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. -// -// Solidity: function GOVERNOR_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeCallerSession) GOVERNORROLE() ([32]byte, error) { - return _FastBridge.Contract.GOVERNORROLE(&_FastBridge.CallOpts) +// ERC165TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ERC165TransactorRaw struct { + Contract *ERC165Transactor // Generic write-only contract binding to access the raw methods on } -// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. -// -// Solidity: function GUARD_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeCaller) GUARDROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "GUARD_ROLE") - +// NewERC165 creates a new instance of ERC165, bound to a specific deployed contract. +func NewERC165(address common.Address, backend bind.ContractBackend) (*ERC165, error) { + contract, err := bindERC165(address, backend, backend, backend) if err != nil { - return *new([32]byte), err + return nil, err } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - + return &ERC165{ERC165Caller: ERC165Caller{contract: contract}, ERC165Transactor: ERC165Transactor{contract: contract}, ERC165Filterer: ERC165Filterer{contract: contract}}, nil } -// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. -// -// Solidity: function GUARD_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeSession) GUARDROLE() ([32]byte, error) { - return _FastBridge.Contract.GUARDROLE(&_FastBridge.CallOpts) +// NewERC165Caller creates a new read-only instance of ERC165, bound to a specific deployed contract. +func NewERC165Caller(address common.Address, caller bind.ContractCaller) (*ERC165Caller, error) { + contract, err := bindERC165(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ERC165Caller{contract: contract}, nil } -// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. -// -// Solidity: function GUARD_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeCallerSession) GUARDROLE() ([32]byte, error) { - return _FastBridge.Contract.GUARDROLE(&_FastBridge.CallOpts) +// NewERC165Transactor creates a new write-only instance of ERC165, bound to a specific deployed contract. +func NewERC165Transactor(address common.Address, transactor bind.ContractTransactor) (*ERC165Transactor, error) { + contract, err := bindERC165(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ERC165Transactor{contract: contract}, nil } -// MINDEADLINEPERIOD is a free data retrieval call binding the contract method 0x820688d5. -// -// Solidity: function MIN_DEADLINE_PERIOD() view returns(uint256) -func (_FastBridge *FastBridgeCaller) MINDEADLINEPERIOD(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "MIN_DEADLINE_PERIOD") +// NewERC165Filterer creates a new log filterer instance of ERC165, bound to a specific deployed contract. +func NewERC165Filterer(address common.Address, filterer bind.ContractFilterer) (*ERC165Filterer, error) { + contract, err := bindERC165(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ERC165Filterer{contract: contract}, nil +} +// bindERC165 binds a generic wrapper to an already deployed contract. +func bindERC165(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ERC165MetaData.GetAbi() if err != nil { - return *new(*big.Int), err + return nil, err } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ERC165 *ERC165Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ERC165.Contract.ERC165Caller.contract.Call(opts, result, method, params...) +} - return out0, err +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ERC165 *ERC165Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC165.Contract.ERC165Transactor.contract.Transfer(opts) +} +// Transact invokes the (paid) contract method with params as input values. +func (_ERC165 *ERC165Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ERC165.Contract.ERC165Transactor.contract.Transact(opts, method, params...) } -// MINDEADLINEPERIOD is a free data retrieval call binding the contract method 0x820688d5. -// -// Solidity: function MIN_DEADLINE_PERIOD() view returns(uint256) -func (_FastBridge *FastBridgeSession) MINDEADLINEPERIOD() (*big.Int, error) { - return _FastBridge.Contract.MINDEADLINEPERIOD(&_FastBridge.CallOpts) +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ERC165 *ERC165CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ERC165.Contract.contract.Call(opts, result, method, params...) } -// MINDEADLINEPERIOD is a free data retrieval call binding the contract method 0x820688d5. -// -// Solidity: function MIN_DEADLINE_PERIOD() view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) MINDEADLINEPERIOD() (*big.Int, error) { - return _FastBridge.Contract.MINDEADLINEPERIOD(&_FastBridge.CallOpts) +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ERC165 *ERC165TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC165.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ERC165 *ERC165TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ERC165.Contract.contract.Transact(opts, method, params...) } -// PROVEPERIOD is a free data retrieval call binding the contract method 0xd3cbc760. +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: function PROVE_PERIOD() view returns(uint256) -func (_FastBridge *FastBridgeCaller) PROVEPERIOD(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_ERC165 *ERC165Caller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "PROVE_PERIOD") + err := _ERC165.contract.Call(opts, &out, "supportsInterface", interfaceId) if err != nil { - return *new(*big.Int), err + return *new(bool), err } - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) return out0, err } -// PROVEPERIOD is a free data retrieval call binding the contract method 0xd3cbc760. +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: function PROVE_PERIOD() view returns(uint256) -func (_FastBridge *FastBridgeSession) PROVEPERIOD() (*big.Int, error) { - return _FastBridge.Contract.PROVEPERIOD(&_FastBridge.CallOpts) +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_ERC165 *ERC165Session) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _ERC165.Contract.SupportsInterface(&_ERC165.CallOpts, interfaceId) } -// PROVEPERIOD is a free data retrieval call binding the contract method 0xd3cbc760. +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: function PROVE_PERIOD() view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) PROVEPERIOD() (*big.Int, error) { - return _FastBridge.Contract.PROVEPERIOD(&_FastBridge.CallOpts) +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_ERC165 *ERC165CallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _ERC165.Contract.SupportsInterface(&_ERC165.CallOpts, interfaceId) } -// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. -// -// Solidity: function RELAYER_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeCaller) RELAYERROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "RELAYER_ROLE") +// EnumerableSetMetaData contains all meta data concerning the EnumerableSet contract. +var EnumerableSetMetaData = &bind.MetaData{ + ABI: "[]", + Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220ccb9bee87c33656dd99a59e58a032b4a522fa9282d7547294079dc934f18ba3f64736f6c63430008140033", +} - if err != nil { - return *new([32]byte), err - } +// EnumerableSetABI is the input ABI used to generate the binding from. +// Deprecated: Use EnumerableSetMetaData.ABI instead. +var EnumerableSetABI = EnumerableSetMetaData.ABI - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) +// EnumerableSetBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use EnumerableSetMetaData.Bin instead. +var EnumerableSetBin = EnumerableSetMetaData.Bin - return out0, err +// DeployEnumerableSet deploys a new Ethereum contract, binding an instance of EnumerableSet to it. +func DeployEnumerableSet(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *EnumerableSet, error) { + parsed, err := EnumerableSetMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(EnumerableSetBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &EnumerableSet{EnumerableSetCaller: EnumerableSetCaller{contract: contract}, EnumerableSetTransactor: EnumerableSetTransactor{contract: contract}, EnumerableSetFilterer: EnumerableSetFilterer{contract: contract}}, nil } -// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. -// -// Solidity: function RELAYER_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeSession) RELAYERROLE() ([32]byte, error) { - return _FastBridge.Contract.RELAYERROLE(&_FastBridge.CallOpts) +// EnumerableSet is an auto generated Go binding around an Ethereum contract. +type EnumerableSet struct { + EnumerableSetCaller // Read-only binding to the contract + EnumerableSetTransactor // Write-only binding to the contract + EnumerableSetFilterer // Log filterer for contract events } -// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. -// -// Solidity: function RELAYER_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeCallerSession) RELAYERROLE() ([32]byte, error) { - return _FastBridge.Contract.RELAYERROLE(&_FastBridge.CallOpts) +// EnumerableSetCaller is an auto generated read-only Go binding around an Ethereum contract. +type EnumerableSetCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// BridgeProofs is a free data retrieval call binding the contract method 0x91ad5039. -// -// Solidity: function bridgeProofs(bytes32 ) view returns(uint96 timestamp, address relayer) -func (_FastBridge *FastBridgeCaller) BridgeProofs(opts *bind.CallOpts, arg0 [32]byte) (struct { - Timestamp *big.Int - Relayer common.Address -}, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "bridgeProofs", arg0) +// EnumerableSetTransactor is an auto generated write-only Go binding around an Ethereum contract. +type EnumerableSetTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} - outstruct := new(struct { - Timestamp *big.Int - Relayer common.Address - }) - if err != nil { - return *outstruct, err - } +// EnumerableSetFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type EnumerableSetFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} - outstruct.Timestamp = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - outstruct.Relayer = *abi.ConvertType(out[1], new(common.Address)).(*common.Address) +// EnumerableSetSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type EnumerableSetSession struct { + Contract *EnumerableSet // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} - return *outstruct, err +// EnumerableSetCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type EnumerableSetCallerSession struct { + Contract *EnumerableSetCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} +// EnumerableSetTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type EnumerableSetTransactorSession struct { + Contract *EnumerableSetTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// BridgeProofs is a free data retrieval call binding the contract method 0x91ad5039. -// -// Solidity: function bridgeProofs(bytes32 ) view returns(uint96 timestamp, address relayer) -func (_FastBridge *FastBridgeSession) BridgeProofs(arg0 [32]byte) (struct { - Timestamp *big.Int - Relayer common.Address -}, error) { - return _FastBridge.Contract.BridgeProofs(&_FastBridge.CallOpts, arg0) +// EnumerableSetRaw is an auto generated low-level Go binding around an Ethereum contract. +type EnumerableSetRaw struct { + Contract *EnumerableSet // Generic contract binding to access the raw methods on } -// BridgeProofs is a free data retrieval call binding the contract method 0x91ad5039. -// -// Solidity: function bridgeProofs(bytes32 ) view returns(uint96 timestamp, address relayer) -func (_FastBridge *FastBridgeCallerSession) BridgeProofs(arg0 [32]byte) (struct { - Timestamp *big.Int - Relayer common.Address -}, error) { - return _FastBridge.Contract.BridgeProofs(&_FastBridge.CallOpts, arg0) +// EnumerableSetCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type EnumerableSetCallerRaw struct { + Contract *EnumerableSetCaller // Generic read-only contract binding to access the raw methods on } -// BridgeRelays is a free data retrieval call binding the contract method 0x8379a24f. -// -// Solidity: function bridgeRelays(bytes32 ) view returns(bool) -func (_FastBridge *FastBridgeCaller) BridgeRelays(opts *bind.CallOpts, arg0 [32]byte) (bool, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "bridgeRelays", arg0) +// EnumerableSetTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type EnumerableSetTransactorRaw struct { + Contract *EnumerableSetTransactor // Generic write-only contract binding to access the raw methods on +} +// NewEnumerableSet creates a new instance of EnumerableSet, bound to a specific deployed contract. +func NewEnumerableSet(address common.Address, backend bind.ContractBackend) (*EnumerableSet, error) { + contract, err := bindEnumerableSet(address, backend, backend, backend) if err != nil { - return *new(bool), err + return nil, err } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - + return &EnumerableSet{EnumerableSetCaller: EnumerableSetCaller{contract: contract}, EnumerableSetTransactor: EnumerableSetTransactor{contract: contract}, EnumerableSetFilterer: EnumerableSetFilterer{contract: contract}}, nil } -// BridgeRelays is a free data retrieval call binding the contract method 0x8379a24f. -// -// Solidity: function bridgeRelays(bytes32 ) view returns(bool) -func (_FastBridge *FastBridgeSession) BridgeRelays(arg0 [32]byte) (bool, error) { - return _FastBridge.Contract.BridgeRelays(&_FastBridge.CallOpts, arg0) +// NewEnumerableSetCaller creates a new read-only instance of EnumerableSet, bound to a specific deployed contract. +func NewEnumerableSetCaller(address common.Address, caller bind.ContractCaller) (*EnumerableSetCaller, error) { + contract, err := bindEnumerableSet(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &EnumerableSetCaller{contract: contract}, nil } -// BridgeRelays is a free data retrieval call binding the contract method 0x8379a24f. -// -// Solidity: function bridgeRelays(bytes32 ) view returns(bool) -func (_FastBridge *FastBridgeCallerSession) BridgeRelays(arg0 [32]byte) (bool, error) { - return _FastBridge.Contract.BridgeRelays(&_FastBridge.CallOpts, arg0) +// NewEnumerableSetTransactor creates a new write-only instance of EnumerableSet, bound to a specific deployed contract. +func NewEnumerableSetTransactor(address common.Address, transactor bind.ContractTransactor) (*EnumerableSetTransactor, error) { + contract, err := bindEnumerableSet(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &EnumerableSetTransactor{contract: contract}, nil } -// BridgeStatuses is a free data retrieval call binding the contract method 0x051287bc. -// -// Solidity: function bridgeStatuses(bytes32 ) view returns(uint8) -func (_FastBridge *FastBridgeCaller) BridgeStatuses(opts *bind.CallOpts, arg0 [32]byte) (uint8, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "bridgeStatuses", arg0) - +// NewEnumerableSetFilterer creates a new log filterer instance of EnumerableSet, bound to a specific deployed contract. +func NewEnumerableSetFilterer(address common.Address, filterer bind.ContractFilterer) (*EnumerableSetFilterer, error) { + contract, err := bindEnumerableSet(address, nil, nil, filterer) if err != nil { - return *new(uint8), err + return nil, err } + return &EnumerableSetFilterer{contract: contract}, nil +} - out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) - - return out0, err +// bindEnumerableSet binds a generic wrapper to an already deployed contract. +func bindEnumerableSet(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := EnumerableSetMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_EnumerableSet *EnumerableSetRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _EnumerableSet.Contract.EnumerableSetCaller.contract.Call(opts, result, method, params...) } -// BridgeStatuses is a free data retrieval call binding the contract method 0x051287bc. -// -// Solidity: function bridgeStatuses(bytes32 ) view returns(uint8) -func (_FastBridge *FastBridgeSession) BridgeStatuses(arg0 [32]byte) (uint8, error) { - return _FastBridge.Contract.BridgeStatuses(&_FastBridge.CallOpts, arg0) +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_EnumerableSet *EnumerableSetRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _EnumerableSet.Contract.EnumerableSetTransactor.contract.Transfer(opts) } -// BridgeStatuses is a free data retrieval call binding the contract method 0x051287bc. -// -// Solidity: function bridgeStatuses(bytes32 ) view returns(uint8) -func (_FastBridge *FastBridgeCallerSession) BridgeStatuses(arg0 [32]byte) (uint8, error) { - return _FastBridge.Contract.BridgeStatuses(&_FastBridge.CallOpts, arg0) +// Transact invokes the (paid) contract method with params as input values. +func (_EnumerableSet *EnumerableSetRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _EnumerableSet.Contract.EnumerableSetTransactor.contract.Transact(opts, method, params...) } -// CanClaim is a free data retrieval call binding the contract method 0xaa9641ab. -// -// Solidity: function canClaim(bytes32 transactionId, address relayer) view returns(bool) -func (_FastBridge *FastBridgeCaller) CanClaim(opts *bind.CallOpts, transactionId [32]byte, relayer common.Address) (bool, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "canClaim", transactionId, relayer) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_EnumerableSet *EnumerableSetCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _EnumerableSet.Contract.contract.Call(opts, result, method, params...) +} +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_EnumerableSet *EnumerableSetTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _EnumerableSet.Contract.contract.Transfer(opts) } -// CanClaim is a free data retrieval call binding the contract method 0xaa9641ab. -// -// Solidity: function canClaim(bytes32 transactionId, address relayer) view returns(bool) -func (_FastBridge *FastBridgeSession) CanClaim(transactionId [32]byte, relayer common.Address) (bool, error) { - return _FastBridge.Contract.CanClaim(&_FastBridge.CallOpts, transactionId, relayer) +// Transact invokes the (paid) contract method with params as input values. +func (_EnumerableSet *EnumerableSetTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _EnumerableSet.Contract.contract.Transact(opts, method, params...) } -// CanClaim is a free data retrieval call binding the contract method 0xaa9641ab. -// -// Solidity: function canClaim(bytes32 transactionId, address relayer) view returns(bool) -func (_FastBridge *FastBridgeCallerSession) CanClaim(transactionId [32]byte, relayer common.Address) (bool, error) { - return _FastBridge.Contract.CanClaim(&_FastBridge.CallOpts, transactionId, relayer) +// FastBridgeMetaData contains all meta data concerning the FastBridge contract. +var FastBridgeMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineNotExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineTooShort\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputePeriodNotPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputePeriodPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MsgValueIncorrect\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SenderIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StatusIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenNotContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransactionRelayed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositRefunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"BridgeProofDisputed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"transactionHash\",\"type\":\"bytes32\"}],\"name\":\"BridgeProofProvided\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"BridgeRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"}],\"name\":\"BridgeRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DISPUTE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_DEADLINE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REFUNDER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REFUND_DELAY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"structIFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"bridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeProofs\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"timestamp\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeRelays\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeStatuses\",\"outputs\":[{\"internalType\":\"enumFastBridge.BridgeStatus\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"canClaim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"dispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"getBridgeTransaction\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originSender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destRecipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originFeeAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"internalType\":\"structIFastBridge.BridgeTransaction\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"destTxHash\",\"type\":\"bytes32\"}],\"name\":\"prove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"refund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "a217fddf": "DEFAULT_ADMIN_ROLE()", + "a5bbe22b": "DISPUTE_PERIOD()", + "bf333f2c": "FEE_BPS()", + "0f5f6ed7": "FEE_RATE_MAX()", + "ccc57490": "GOVERNOR_ROLE()", + "03ed0ee5": "GUARD_ROLE()", + "820688d5": "MIN_DEADLINE_PERIOD()", + "5960ccf2": "REFUNDER_ROLE()", + "190da595": "REFUND_DELAY()", + "926d7d7f": "RELAYER_ROLE()", + "45851694": "bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))", + "91ad5039": "bridgeProofs(bytes32)", + "8379a24f": "bridgeRelays(bytes32)", + "051287bc": "bridgeStatuses(bytes32)", + "aa9641ab": "canClaim(bytes32,address)", + "e00a83e0": "chainGasAmount()", + "41fcb612": "claim(bytes,address)", + "a3ec191a": "deployBlock()", + "add98c70": "dispute(bytes32)", + "ac11fb1a": "getBridgeTransaction(bytes)", + "248a9ca3": "getRoleAdmin(bytes32)", + "9010d07c": "getRoleMember(bytes32,uint256)", + "ca15c873": "getRoleMemberCount(bytes32)", + "2f2ff15d": "grantRole(bytes32,address)", + "91d14854": "hasRole(bytes32,address)", + "affed0e0": "nonce()", + "58f85880": "protocolFeeRate()", + "dcf844a7": "protocolFees(address)", + "886d36ff": "prove(bytes,bytes32)", + "5eb7d946": "refund(bytes)", + "8f0d6f17": "relay(bytes)", + "36568abe": "renounceRole(bytes32,address)", + "d547741f": "revokeRole(bytes32,address)", + "b250fe6b": "setChainGasAmount(uint256)", + "b13aa2d6": "setProtocolFeeRate(uint256)", + "01ffc9a7": "supportsInterface(bytes4)", + "06f333f2": "sweepProtocolFees(address,address)", + }, + Bin: "0x60a06040523480156200001157600080fd5b5060405162002d7a38038062002d7a833981016040819052620000349162000194565b80620000426000826200004f565b50504360805250620001bf565b6000806200005e84846200008c565b90508015620000835760008481526001602052604090206200008190846200013a565b505b90505b92915050565b6000828152602081815260408083206001600160a01b038516845290915281205460ff1662000131576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620000e83390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600162000086565b50600062000086565b600062000083836001600160a01b0384166000818152600183016020526040812054620001315750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000086565b600060208284031215620001a757600080fd5b81516001600160a01b03811681146200008357600080fd5b608051612b9f620001db60003960006106510152612b9f6000f3fe60806040526004361061026a5760003560e01c80639010d07c11610153578063add98c70116100cb578063ca15c8731161007f578063d547741f11610064578063d547741f146107a1578063dcf844a7146107c1578063e00a83e0146107ee57600080fd5b8063ca15c8731461074d578063ccc574901461076d57600080fd5b8063b13aa2d6116100b0578063b13aa2d6146106f6578063b250fe6b14610716578063bf333f2c1461073657600080fd5b8063add98c70146106c0578063affed0e0146106e057600080fd5b8063a217fddf11610122578063a5bbe22b11610107578063a5bbe22b1461047f578063aa9641ab14610673578063ac11fb1a1461069357600080fd5b8063a217fddf1461062a578063a3ec191a1461063f57600080fd5b80639010d07c146104f857806391ad50391461053057806391d14854146105b2578063926d7d7f146105f657600080fd5b806341fcb612116101e65780635eb7d946116101b55780638379a24f1161019a5780638379a24f14610495578063886d36ff146104c55780638f0d6f17146104e557600080fd5b80635eb7d9461461045f578063820688d51461047f57600080fd5b806341fcb612146103e2578063458516941461040257806358f85880146104155780635960ccf21461042b57600080fd5b80630f5f6ed71161023d578063248a9ca311610222578063248a9ca3146103725780632f2ff15d146103a257806336568abe146103c257600080fd5b80630f5f6ed714610345578063190da5951461035b57600080fd5b806301ffc9a71461026f57806303ed0ee5146102a4578063051287bc146102e657806306f333f214610323575b600080fd5b34801561027b57600080fd5b5061028f61028a3660046122fc565b610804565b60405190151581526020015b60405180910390f35b3480156102b057600080fd5b506102d87f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b60405190815260200161029b565b3480156102f257600080fd5b5061031661030136600461233e565b60056020526000908152604090205460ff1681565b60405161029b9190612386565b34801561032f57600080fd5b5061034361033e3660046123ec565b610860565b005b34801561035157600080fd5b506102d861271081565b34801561036757600080fd5b506102d862093a8081565b34801561037e57600080fd5b506102d861038d36600461233e565b60009081526020819052604090206001015490565b3480156103ae57600080fd5b506103436103bd366004612425565b610927565b3480156103ce57600080fd5b506103436103dd366004612425565b610952565b3480156103ee57600080fd5b506103436103fd366004612572565b61099e565b6103436104103660046125ef565b610bd7565b34801561042157600080fd5b506102d860025481565b34801561043757600080fd5b506102d87fdb9556138406326f00296e13ea2ad7db24ba82381212d816b1a40c23b466b32781565b34801561046b57600080fd5b5061034361047a366004612692565b610ee5565b34801561048b57600080fd5b506102d861070881565b3480156104a157600080fd5b5061028f6104b036600461233e565b60076020526000908152604090205460ff1681565b3480156104d157600080fd5b506103436104e03660046126cf565b6110bd565b6103436104f3366004612692565b6111f0565b34801561050457600080fd5b50610518610513366004612714565b611437565b6040516001600160a01b03909116815260200161029b565b34801561053c57600080fd5b5061058661054b36600461233e565b6006602052600090815260409020546bffffffffffffffffffffffff8116906c0100000000000000000000000090046001600160a01b031682565b604080516bffffffffffffffffffffffff90931683526001600160a01b0390911660208301520161029b565b3480156105be57600080fd5b5061028f6105cd366004612425565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561060257600080fd5b506102d87fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b34801561063657600080fd5b506102d8600081565b34801561064b57600080fd5b506102d87f000000000000000000000000000000000000000000000000000000000000000081565b34801561067f57600080fd5b5061028f61068e366004612425565b611456565b34801561069f57600080fd5b506106b36106ae366004612692565b611559565b60405161029b9190612736565b3480156106cc57600080fd5b506103436106db36600461233e565b6115cc565b3480156106ec57600080fd5b506102d860085481565b34801561070257600080fd5b5061034361071136600461233e565b611735565b34801561072257600080fd5b5061034361073136600461233e565b611817565b34801561074257600080fd5b506102d8620f424081565b34801561075957600080fd5b506102d861076836600461233e565b61187f565b34801561077957600080fd5b506102d87f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b3480156107ad57600080fd5b506103436107bc366004612425565b611896565b3480156107cd57600080fd5b506102d86107dc36600461281c565b60036020526000908152604090205481565b3480156107fa57600080fd5b506102d860045481565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f00000000000000000000000000000000000000000000000000000000148061085a575061085a826118bb565b92915050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561088a81611952565b6001600160a01b038316600090815260036020526040812054908190036108b15750505050565b6001600160a01b0384166000818152600360205260408120556108d590848361195f565b604080516001600160a01b038087168252851660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b505050565b60008281526020819052604090206001015461094281611952565b61094c8383611a82565b50505050565b6001600160a01b0381163314610994576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109228282611ab7565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc46109c881611952565b8251602084012060006109da85611559565b9050600260008381526005602052604090205460ff166004811115610a0157610a01612357565b14610a38576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660209081526040918290208251808401909352546bffffffffffffffffffffffff811683526c0100000000000000000000000090046001600160a01b03169082018190523314610abb576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611610b08576040517f1992d0bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600560205260409020805460ff1916600317905561010082015115610b645761010082015160808301516001600160a01b031660009081526003602052604081208054909190610b5e908490612868565b90915550505b608082015160c0830151610b826001600160a01b038316888361195f565b604080516001600160a01b03848116825260208201849052891691339188917f582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac67891015b60405180910390a45050505050505050565b46816000015163ffffffff1603610c1a576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a08101511580610c2d575060c0810151155b15610c64576040517fe38820c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608101516001600160a01b03161580610c89575060808101516001600160a01b0316155b15610cc0576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ccc61070842612868565b8161010001511015610d0a576040517f04b7fcc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d1f3083606001518460a00151611ae4565b90506000806002541115610d4c57620f424060025483610d3f919061287b565b610d499190612892565b90505b610d5681836128cd565b915060006040518061018001604052804663ffffffff168152602001856000015163ffffffff16815260200185602001516001600160a01b0316815260200185604001516001600160a01b0316815260200185606001516001600160a01b0316815260200185608001516001600160a01b031681526020018481526020018560c0015181526020018381526020018560e0015115158152602001856101000151815260200160086000815480929190610e0e906128e0565b909155509052604051610e249190602001612736565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152828252805160208083019190912060008181526005835293909320805460ff191660011790558701518751606089015160808a015160c08b015160e08c015195985095966001600160a01b039094169587957f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a95610ed6958b959094909390928e9261293c565b60405180910390a35050505050565b805160208201206000610ef783611559565b3360009081527fd2043bf65931af3dbecf60d0db8f40e4160406d7beb00522f4200cf4944a1eb8602052604090205490915060ff1615610f74578061014001514211610f6f576040517fe15ff9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fc0565b62093a80816101400151610f889190612868565b4211610fc0576040517fe15ff9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008381526005602052604090205460ff166004811115610fe557610fe5612357565b1461101c576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260056020526040808220805460ff19166004179055820151608083015161010084015160c0850151929391926110579190612868565b905061106d6001600160a01b038316848361195f565b604080516001600160a01b0384811682526020820184905285169187917fb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958910160405180910390a3505050505050565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc46110e781611952565b82516020840120600160008281526005602052604090205460ff16600481111561111357611113612357565b1461114a576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526005602090815260408083208054600260ff19909116179055805180820182526bffffffffffffffffffffffff4281168252338285018181528787526006865295849020925195516001600160a01b03166c0100000000000000000000000002959091169490941790555185815283917f4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4910160405180910390a350505050565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc461121a81611952565b81516020830120600061122c84611559565b90504663ffffffff16816020015163ffffffff1614611277576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8061014001514211156112b6576040517f559895a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526007602052604090205460ff16156112ff576040517fbef7bb7d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600760205260409020805460ff19166001179055606081015160a082015160e083015160045461012085015161134857506000611342848484611ae4565b506113b9565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b0384160161138c5761134284846113878486612868565b611ae4565b611397848484611ae4565b506113b78473eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee83611ae4565b505b845160808087015160a08089015160c0808b015160e08c01516040805163ffffffff90991689526001600160a01b0396871660208a0152938616938801939093526060870152938501528301849052861691339189917ff8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c9101610bc5565b600082815260016020526040812061144f9083611cb3565b9392505050565b6000600260008481526005602052604090205460ff16600481111561147d5761147d612357565b146114b4576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600660209081526040918290208251808401909352546bffffffffffffffffffffffff811683526001600160a01b036c01000000000000000000000000909104811691830182905284161461153a576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611949350505050565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201528251909161085a91840181019084016129ed565b7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d6115f681611952565b600260008381526005602052604090205460ff16600481111561161b5761161b612357565b14611652576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660209081526040918290208251808401909352546bffffffffffffffffffffffff8082168085526c010000000000000000000000009092046001600160a01b031693909201929092526107089142031611156116e1576040517f3e908aac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040808320805460ff19166001179055600690915280822082905551339184917f0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad49190a35050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561175f81611952565b6127108211156117d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064015b60405180910390fd5b600280549083905560408051828152602081018590527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a1505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561184181611952565b600480549083905560408051828152602081018590527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa910161180a565b600081815260016020526040812061085a90611cbf565b6000828152602081905260409020600101546118b181611952565b61094c8383611ab7565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061085a57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461085a565b61195c8133611cc9565b50565b306001600160a01b0383160361197457505050565b8060000361198157505050565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03841601611a6e576000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146119fe576040519150601f19603f3d011682016040523d82523d6000602084013e611a03565b606091505b505090508061094c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c65640000000000000000000000000060448201526064016117c7565b6109226001600160a01b0384168383611d39565b600080611a8f8484611dad565b9050801561144f576000848152600160205260409020611aaf9084611e57565b509392505050565b600080611ac48484611e6c565b9050801561144f576000848152600160205260409020611aaf9084611eef565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611c4d57611b1c836001600160a01b0316611f04565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528416906370a0823190602401602060405180830381865afa158015611b7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9f9190612ab9565b9050611bb66001600160a01b038416338685611faa565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528291908516906370a0823190602401602060405180830381865afa158015611c18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c3c9190612ab9565b611c4691906128cd565b905061144f565b348214611c86576040517f81de0bf300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0384163014611caa57611caa6001600160a01b038416858461195f565b50349392505050565b600061144f8383611fe3565b600061085a825490565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16611d35576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602481018390526044016117c7565b5050565b6040516001600160a01b0383811660248301526044820183905261092291859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061200d565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16611e4f576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055611e073390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161085a565b50600061085a565b600061144f836001600160a01b038416612089565b6000828152602081815260408083206001600160a01b038516845290915281205460ff1615611e4f576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161085a565b600061144f836001600160a01b0384166120d0565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03821601611f66576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03163b60000361195c576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b03848116602483015283811660448301526064820183905261094c9186918216906323b872dd90608401611d66565b6000826000018281548110611ffa57611ffa612ad2565b9060005260206000200154905092915050565b60006120226001600160a01b038416836121c3565b905080516000141580156120475750808060200190518101906120459190612b01565b155b15610922576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024016117c7565b6000818152600183016020526040812054611e4f5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561085a565b600081815260018301602052604081205480156121b95760006120f46001836128cd565b8554909150600090612108906001906128cd565b905080821461216d57600086600001828154811061212857612128612ad2565b906000526020600020015490508087600001848154811061214b5761214b612ad2565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061217e5761217e612b1e565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061085a565b600091505061085a565b606061144f8383600084600080856001600160a01b031684866040516121e99190612b4d565b60006040518083038185875af1925050503d8060008114612226576040519150601f19603f3d011682016040523d82523d6000602084013e61222b565b606091505b509150915061223b868383612245565b9695505050505050565b60608261225a57612255826122ba565b61144f565b815115801561227157506001600160a01b0384163b155b156122b3576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016117c7565b508061144f565b8051156122ca5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561230e57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461144f57600080fd5b60006020828403121561235057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600583106123c1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6001600160a01b038116811461195c57600080fd5b80356123e7816123c7565b919050565b600080604083850312156123ff57600080fd5b823561240a816123c7565b9150602083013561241a816123c7565b809150509250929050565b6000806040838503121561243857600080fd5b82359150602083013561241a816123c7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171561249d5761249d61244a565b60405290565b604051610180810167ffffffffffffffff8111828210171561249d5761249d61244a565b600082601f8301126124d857600080fd5b813567ffffffffffffffff808211156124f3576124f361244a565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156125395761253961244a565b8160405283815286602085880101111561255257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806040838503121561258557600080fd5b823567ffffffffffffffff81111561259c57600080fd5b6125a8858286016124c7565b925050602083013561241a816123c7565b63ffffffff8116811461195c57600080fd5b80356123e7816125b9565b801515811461195c57600080fd5b80356123e7816125d6565b6000610120828403121561260257600080fd5b61260a612479565b612613836125cb565b8152612621602084016123dc565b6020820152612632604084016123dc565b6040820152612643606084016123dc565b6060820152612654608084016123dc565b608082015260a083013560a082015260c083013560c082015261267960e084016125e4565b60e0820152610100928301359281019290925250919050565b6000602082840312156126a457600080fd5b813567ffffffffffffffff8111156126bb57600080fd5b6126c7848285016124c7565b949350505050565b600080604083850312156126e257600080fd5b823567ffffffffffffffff8111156126f957600080fd5b612705858286016124c7565b95602094909401359450505050565b6000806040838503121561272757600080fd5b50508035926020909101359150565b815163ffffffff1681526101808101602083015161275c602084018263ffffffff169052565b50604083015161277760408401826001600160a01b03169052565b50606083015161279260608401826001600160a01b03169052565b5060808301516127ad60808401826001600160a01b03169052565b5060a08301516127c860a08401826001600160a01b03169052565b5060c083015160c083015260e083015160e0830152610100808401518184015250610120808401516127fd8285018215159052565b5050610140838101519083015261016092830151929091019190915290565b60006020828403121561282e57600080fd5b813561144f816123c7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561085a5761085a612839565b808202811582820484141761085a5761085a612839565b6000826128c8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561085a5761085a612839565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361291157612911612839565b5060010190565b60005b8381101561293357818101518382015260200161291b565b50506000910152565b60e08152600088518060e084015261010061295d8282860160208e01612918565b63ffffffff9990991660208401526001600160a01b039788166040840152959096166060820152608081019390935260a0830191909152151560c0820152601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190910192915050565b80516123e7816125b9565b80516123e7816123c7565b80516123e7816125d6565b60006101808284031215612a0057600080fd5b612a086124a3565b612a11836129cc565b8152612a1f602084016129cc565b6020820152612a30604084016129d7565b6040820152612a41606084016129d7565b6060820152612a52608084016129d7565b6080820152612a6360a084016129d7565b60a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120612a968185016129e2565b908201526101408381015190820152610160928301519281019290925250919050565b600060208284031215612acb57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215612b1357600080fd5b815161144f816125d6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612b5f818460208701612918565b919091019291505056fea26469706673582212207d038d8dfad42c58e5149b646b9e05914f990dd941b51e06388a96d1ed46308264736f6c63430008140033", } -// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. -// -// Solidity: function chainGasAmount() view returns(uint256) -func (_FastBridge *FastBridgeCaller) ChainGasAmount(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "chainGasAmount") +// FastBridgeABI is the input ABI used to generate the binding from. +// Deprecated: Use FastBridgeMetaData.ABI instead. +var FastBridgeABI = FastBridgeMetaData.ABI - if err != nil { - return *new(*big.Int), err - } +// Deprecated: Use FastBridgeMetaData.Sigs instead. +// FastBridgeFuncSigs maps the 4-byte function signature to its string representation. +var FastBridgeFuncSigs = FastBridgeMetaData.Sigs - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) +// FastBridgeBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use FastBridgeMetaData.Bin instead. +var FastBridgeBin = FastBridgeMetaData.Bin - return out0, err +// DeployFastBridge deploys a new Ethereum contract, binding an instance of FastBridge to it. +func DeployFastBridge(auth *bind.TransactOpts, backend bind.ContractBackend, _owner common.Address) (common.Address, *types.Transaction, *FastBridge, error) { + parsed, err := FastBridgeMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(FastBridgeBin), backend, _owner) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &FastBridge{FastBridgeCaller: FastBridgeCaller{contract: contract}, FastBridgeTransactor: FastBridgeTransactor{contract: contract}, FastBridgeFilterer: FastBridgeFilterer{contract: contract}}, nil } -// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. -// -// Solidity: function chainGasAmount() view returns(uint256) -func (_FastBridge *FastBridgeSession) ChainGasAmount() (*big.Int, error) { - return _FastBridge.Contract.ChainGasAmount(&_FastBridge.CallOpts) +// FastBridge is an auto generated Go binding around an Ethereum contract. +type FastBridge struct { + FastBridgeCaller // Read-only binding to the contract + FastBridgeTransactor // Write-only binding to the contract + FastBridgeFilterer // Log filterer for contract events } -// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. -// -// Solidity: function chainGasAmount() view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) ChainGasAmount() (*big.Int, error) { - return _FastBridge.Contract.ChainGasAmount(&_FastBridge.CallOpts) +// FastBridgeCaller is an auto generated read-only Go binding around an Ethereum contract. +type FastBridgeCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// DeployBlock is a free data retrieval call binding the contract method 0xa3ec191a. -// -// Solidity: function deployBlock() view returns(uint256) -func (_FastBridge *FastBridgeCaller) DeployBlock(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "deployBlock") +// FastBridgeTransactor is an auto generated write-only Go binding around an Ethereum contract. +type FastBridgeTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} - if err != nil { - return *new(*big.Int), err - } +// FastBridgeFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type FastBridgeFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) +// FastBridgeSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type FastBridgeSession struct { + Contract *FastBridge // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} - return out0, err +// FastBridgeCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type FastBridgeCallerSession struct { + Contract *FastBridgeCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} +// FastBridgeTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type FastBridgeTransactorSession struct { + Contract *FastBridgeTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// DeployBlock is a free data retrieval call binding the contract method 0xa3ec191a. -// -// Solidity: function deployBlock() view returns(uint256) -func (_FastBridge *FastBridgeSession) DeployBlock() (*big.Int, error) { - return _FastBridge.Contract.DeployBlock(&_FastBridge.CallOpts) +// FastBridgeRaw is an auto generated low-level Go binding around an Ethereum contract. +type FastBridgeRaw struct { + Contract *FastBridge // Generic contract binding to access the raw methods on } -// DeployBlock is a free data retrieval call binding the contract method 0xa3ec191a. -// -// Solidity: function deployBlock() view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) DeployBlock() (*big.Int, error) { - return _FastBridge.Contract.DeployBlock(&_FastBridge.CallOpts) +// FastBridgeCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type FastBridgeCallerRaw struct { + Contract *FastBridgeCaller // Generic read-only contract binding to access the raw methods on } -// GetBridgeTransaction is a free data retrieval call binding the contract method 0xac11fb1a. -// -// Solidity: function getBridgeTransaction(bytes request) pure returns((uint32,uint32,address,address,address,address,uint256,uint256,uint256,bool,uint256,uint256)) -func (_FastBridge *FastBridgeCaller) GetBridgeTransaction(opts *bind.CallOpts, request []byte) (IFastBridgeBridgeTransaction, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "getBridgeTransaction", request) +// FastBridgeTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type FastBridgeTransactorRaw struct { + Contract *FastBridgeTransactor // Generic write-only contract binding to access the raw methods on +} +// NewFastBridge creates a new instance of FastBridge, bound to a specific deployed contract. +func NewFastBridge(address common.Address, backend bind.ContractBackend) (*FastBridge, error) { + contract, err := bindFastBridge(address, backend, backend, backend) if err != nil { - return *new(IFastBridgeBridgeTransaction), err + return nil, err } - - out0 := *abi.ConvertType(out[0], new(IFastBridgeBridgeTransaction)).(*IFastBridgeBridgeTransaction) - - return out0, err - + return &FastBridge{FastBridgeCaller: FastBridgeCaller{contract: contract}, FastBridgeTransactor: FastBridgeTransactor{contract: contract}, FastBridgeFilterer: FastBridgeFilterer{contract: contract}}, nil } -// GetBridgeTransaction is a free data retrieval call binding the contract method 0xac11fb1a. -// -// Solidity: function getBridgeTransaction(bytes request) pure returns((uint32,uint32,address,address,address,address,uint256,uint256,uint256,bool,uint256,uint256)) -func (_FastBridge *FastBridgeSession) GetBridgeTransaction(request []byte) (IFastBridgeBridgeTransaction, error) { - return _FastBridge.Contract.GetBridgeTransaction(&_FastBridge.CallOpts, request) +// NewFastBridgeCaller creates a new read-only instance of FastBridge, bound to a specific deployed contract. +func NewFastBridgeCaller(address common.Address, caller bind.ContractCaller) (*FastBridgeCaller, error) { + contract, err := bindFastBridge(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &FastBridgeCaller{contract: contract}, nil } -// GetBridgeTransaction is a free data retrieval call binding the contract method 0xac11fb1a. -// -// Solidity: function getBridgeTransaction(bytes request) pure returns((uint32,uint32,address,address,address,address,uint256,uint256,uint256,bool,uint256,uint256)) -func (_FastBridge *FastBridgeCallerSession) GetBridgeTransaction(request []byte) (IFastBridgeBridgeTransaction, error) { - return _FastBridge.Contract.GetBridgeTransaction(&_FastBridge.CallOpts, request) +// NewFastBridgeTransactor creates a new write-only instance of FastBridge, bound to a specific deployed contract. +func NewFastBridgeTransactor(address common.Address, transactor bind.ContractTransactor) (*FastBridgeTransactor, error) { + contract, err := bindFastBridge(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &FastBridgeTransactor{contract: contract}, nil } -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_FastBridge *FastBridgeCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "getRoleAdmin", role) - +// NewFastBridgeFilterer creates a new log filterer instance of FastBridge, bound to a specific deployed contract. +func NewFastBridgeFilterer(address common.Address, filterer bind.ContractFilterer) (*FastBridgeFilterer, error) { + contract, err := bindFastBridge(address, nil, nil, filterer) if err != nil { - return *new([32]byte), err + return nil, err } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - + return &FastBridgeFilterer{contract: contract}, nil } -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_FastBridge *FastBridgeSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { - return _FastBridge.Contract.GetRoleAdmin(&_FastBridge.CallOpts, role) +// bindFastBridge binds a generic wrapper to an already deployed contract. +func bindFastBridge(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := FastBridgeMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_FastBridge *FastBridgeCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { - return _FastBridge.Contract.GetRoleAdmin(&_FastBridge.CallOpts, role) +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_FastBridge *FastBridgeRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _FastBridge.Contract.FastBridgeCaller.contract.Call(opts, result, method, params...) } -// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_FastBridge *FastBridgeRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _FastBridge.Contract.FastBridgeTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_FastBridge *FastBridgeRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _FastBridge.Contract.FastBridgeTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_FastBridge *FastBridgeCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _FastBridge.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_FastBridge *FastBridgeTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _FastBridge.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_FastBridge *FastBridgeTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _FastBridge.Contract.contract.Transact(opts, method, params...) +} + +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. // -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_FastBridge *FastBridgeCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "hasRole", role, account) + err := _FastBridge.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") if err != nil { - return *new(bool), err + return *new([32]byte), err } - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) return out0, err } -// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. // -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_FastBridge *FastBridgeSession) HasRole(role [32]byte, account common.Address) (bool, error) { - return _FastBridge.Contract.HasRole(&_FastBridge.CallOpts, role, account) +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeSession) DEFAULTADMINROLE() ([32]byte, error) { + return _FastBridge.Contract.DEFAULTADMINROLE(&_FastBridge.CallOpts) } -// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. // -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_FastBridge *FastBridgeCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { - return _FastBridge.Contract.HasRole(&_FastBridge.CallOpts, role, account) +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCallerSession) DEFAULTADMINROLE() ([32]byte, error) { + return _FastBridge.Contract.DEFAULTADMINROLE(&_FastBridge.CallOpts) } -// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. +// DISPUTEPERIOD is a free data retrieval call binding the contract method 0xa5bbe22b. // -// Solidity: function nonce() view returns(uint256) -func (_FastBridge *FastBridgeCaller) Nonce(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function DISPUTE_PERIOD() view returns(uint256) +func (_FastBridge *FastBridgeCaller) DISPUTEPERIOD(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "nonce") + err := _FastBridge.contract.Call(opts, &out, "DISPUTE_PERIOD") if err != nil { return *new(*big.Int), err @@ -4739,26 +4429,26 @@ func (_FastBridge *FastBridgeCaller) Nonce(opts *bind.CallOpts) (*big.Int, error } -// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. +// DISPUTEPERIOD is a free data retrieval call binding the contract method 0xa5bbe22b. // -// Solidity: function nonce() view returns(uint256) -func (_FastBridge *FastBridgeSession) Nonce() (*big.Int, error) { - return _FastBridge.Contract.Nonce(&_FastBridge.CallOpts) +// Solidity: function DISPUTE_PERIOD() view returns(uint256) +func (_FastBridge *FastBridgeSession) DISPUTEPERIOD() (*big.Int, error) { + return _FastBridge.Contract.DISPUTEPERIOD(&_FastBridge.CallOpts) } -// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. +// DISPUTEPERIOD is a free data retrieval call binding the contract method 0xa5bbe22b. // -// Solidity: function nonce() view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) Nonce() (*big.Int, error) { - return _FastBridge.Contract.Nonce(&_FastBridge.CallOpts) +// Solidity: function DISPUTE_PERIOD() view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) DISPUTEPERIOD() (*big.Int, error) { + return _FastBridge.Contract.DISPUTEPERIOD(&_FastBridge.CallOpts) } -// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. // -// Solidity: function protocolFeeRate() view returns(uint256) -func (_FastBridge *FastBridgeCaller) ProtocolFeeRate(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function FEE_BPS() view returns(uint256) +func (_FastBridge *FastBridgeCaller) FEEBPS(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "protocolFeeRate") + err := _FastBridge.contract.Call(opts, &out, "FEE_BPS") if err != nil { return *new(*big.Int), err @@ -4770,26 +4460,26 @@ func (_FastBridge *FastBridgeCaller) ProtocolFeeRate(opts *bind.CallOpts) (*big. } -// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. // -// Solidity: function protocolFeeRate() view returns(uint256) -func (_FastBridge *FastBridgeSession) ProtocolFeeRate() (*big.Int, error) { - return _FastBridge.Contract.ProtocolFeeRate(&_FastBridge.CallOpts) +// Solidity: function FEE_BPS() view returns(uint256) +func (_FastBridge *FastBridgeSession) FEEBPS() (*big.Int, error) { + return _FastBridge.Contract.FEEBPS(&_FastBridge.CallOpts) } -// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. // -// Solidity: function protocolFeeRate() view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) ProtocolFeeRate() (*big.Int, error) { - return _FastBridge.Contract.ProtocolFeeRate(&_FastBridge.CallOpts) +// Solidity: function FEE_BPS() view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) FEEBPS() (*big.Int, error) { + return _FastBridge.Contract.FEEBPS(&_FastBridge.CallOpts) } -// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. +// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. // -// Solidity: function protocolFees(address ) view returns(uint256) -func (_FastBridge *FastBridgeCaller) ProtocolFees(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { +// Solidity: function FEE_RATE_MAX() view returns(uint256) +func (_FastBridge *FastBridgeCaller) FEERATEMAX(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "protocolFees", arg0) + err := _FastBridge.contract.Call(opts, &out, "FEE_RATE_MAX") if err != nil { return *new(*big.Int), err @@ -4801,1386 +4491,940 @@ func (_FastBridge *FastBridgeCaller) ProtocolFees(opts *bind.CallOpts, arg0 comm } -// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. +// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. // -// Solidity: function protocolFees(address ) view returns(uint256) -func (_FastBridge *FastBridgeSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { - return _FastBridge.Contract.ProtocolFees(&_FastBridge.CallOpts, arg0) +// Solidity: function FEE_RATE_MAX() view returns(uint256) +func (_FastBridge *FastBridgeSession) FEERATEMAX() (*big.Int, error) { + return _FastBridge.Contract.FEERATEMAX(&_FastBridge.CallOpts) } -// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. +// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. // -// Solidity: function protocolFees(address ) view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { - return _FastBridge.Contract.ProtocolFees(&_FastBridge.CallOpts, arg0) +// Solidity: function FEE_RATE_MAX() view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) FEERATEMAX() (*big.Int, error) { + return _FastBridge.Contract.FEERATEMAX(&_FastBridge.CallOpts) } -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. // -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_FastBridge *FastBridgeCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { +// Solidity: function GOVERNOR_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCaller) GOVERNORROLE(opts *bind.CallOpts) ([32]byte, error) { var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "supportsInterface", interfaceId) + err := _FastBridge.contract.Call(opts, &out, "GOVERNOR_ROLE") if err != nil { - return *new(bool), err + return *new([32]byte), err } - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) return out0, err } -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. // -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_FastBridge *FastBridgeSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _FastBridge.Contract.SupportsInterface(&_FastBridge.CallOpts, interfaceId) +// Solidity: function GOVERNOR_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeSession) GOVERNORROLE() ([32]byte, error) { + return _FastBridge.Contract.GOVERNORROLE(&_FastBridge.CallOpts) } -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. // -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_FastBridge *FastBridgeCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _FastBridge.Contract.SupportsInterface(&_FastBridge.CallOpts, interfaceId) +// Solidity: function GOVERNOR_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCallerSession) GOVERNORROLE() ([32]byte, error) { + return _FastBridge.Contract.GOVERNORROLE(&_FastBridge.CallOpts) } -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. +// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. // -// Solidity: function addGovernor(address _governor) returns() -func (_FastBridge *FastBridgeTransactor) AddGovernor(opts *bind.TransactOpts, _governor common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "addGovernor", _governor) -} +// Solidity: function GUARD_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCaller) GUARDROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "GUARD_ROLE") -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. -// -// Solidity: function addGovernor(address _governor) returns() -func (_FastBridge *FastBridgeSession) AddGovernor(_governor common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.AddGovernor(&_FastBridge.TransactOpts, _governor) -} + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. -// -// Solidity: function addGovernor(address _governor) returns() -func (_FastBridge *FastBridgeTransactorSession) AddGovernor(_governor common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.AddGovernor(&_FastBridge.TransactOpts, _governor) } -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. +// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. // -// Solidity: function addGuard(address _guard) returns() -func (_FastBridge *FastBridgeTransactor) AddGuard(opts *bind.TransactOpts, _guard common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "addGuard", _guard) +// Solidity: function GUARD_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeSession) GUARDROLE() ([32]byte, error) { + return _FastBridge.Contract.GUARDROLE(&_FastBridge.CallOpts) } -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. +// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. // -// Solidity: function addGuard(address _guard) returns() -func (_FastBridge *FastBridgeSession) AddGuard(_guard common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.AddGuard(&_FastBridge.TransactOpts, _guard) +// Solidity: function GUARD_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCallerSession) GUARDROLE() ([32]byte, error) { + return _FastBridge.Contract.GUARDROLE(&_FastBridge.CallOpts) } -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. +// MINDEADLINEPERIOD is a free data retrieval call binding the contract method 0x820688d5. // -// Solidity: function addGuard(address _guard) returns() -func (_FastBridge *FastBridgeTransactorSession) AddGuard(_guard common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.AddGuard(&_FastBridge.TransactOpts, _guard) +// Solidity: function MIN_DEADLINE_PERIOD() view returns(uint256) +func (_FastBridge *FastBridgeCaller) MINDEADLINEPERIOD(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "MIN_DEADLINE_PERIOD") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. +// MINDEADLINEPERIOD is a free data retrieval call binding the contract method 0x820688d5. // -// Solidity: function addRelayer(address _relayer) returns() -func (_FastBridge *FastBridgeTransactor) AddRelayer(opts *bind.TransactOpts, _relayer common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "addRelayer", _relayer) +// Solidity: function MIN_DEADLINE_PERIOD() view returns(uint256) +func (_FastBridge *FastBridgeSession) MINDEADLINEPERIOD() (*big.Int, error) { + return _FastBridge.Contract.MINDEADLINEPERIOD(&_FastBridge.CallOpts) } -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. +// MINDEADLINEPERIOD is a free data retrieval call binding the contract method 0x820688d5. // -// Solidity: function addRelayer(address _relayer) returns() -func (_FastBridge *FastBridgeSession) AddRelayer(_relayer common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.AddRelayer(&_FastBridge.TransactOpts, _relayer) +// Solidity: function MIN_DEADLINE_PERIOD() view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) MINDEADLINEPERIOD() (*big.Int, error) { + return _FastBridge.Contract.MINDEADLINEPERIOD(&_FastBridge.CallOpts) } -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. +// REFUNDERROLE is a free data retrieval call binding the contract method 0x5960ccf2. // -// Solidity: function addRelayer(address _relayer) returns() -func (_FastBridge *FastBridgeTransactorSession) AddRelayer(_relayer common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.AddRelayer(&_FastBridge.TransactOpts, _relayer) +// Solidity: function REFUNDER_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCaller) REFUNDERROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "REFUNDER_ROLE") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -// Bridge is a paid mutator transaction binding the contract method 0x45851694. +// REFUNDERROLE is a free data retrieval call binding the contract method 0x5960ccf2. // -// Solidity: function bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256) params) payable returns() -func (_FastBridge *FastBridgeTransactor) Bridge(opts *bind.TransactOpts, params IFastBridgeBridgeParams) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "bridge", params) +// Solidity: function REFUNDER_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeSession) REFUNDERROLE() ([32]byte, error) { + return _FastBridge.Contract.REFUNDERROLE(&_FastBridge.CallOpts) } -// Bridge is a paid mutator transaction binding the contract method 0x45851694. +// REFUNDERROLE is a free data retrieval call binding the contract method 0x5960ccf2. // -// Solidity: function bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256) params) payable returns() -func (_FastBridge *FastBridgeSession) Bridge(params IFastBridgeBridgeParams) (*types.Transaction, error) { - return _FastBridge.Contract.Bridge(&_FastBridge.TransactOpts, params) +// Solidity: function REFUNDER_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCallerSession) REFUNDERROLE() ([32]byte, error) { + return _FastBridge.Contract.REFUNDERROLE(&_FastBridge.CallOpts) } -// Bridge is a paid mutator transaction binding the contract method 0x45851694. +// REFUNDDELAY is a free data retrieval call binding the contract method 0x190da595. // -// Solidity: function bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256) params) payable returns() -func (_FastBridge *FastBridgeTransactorSession) Bridge(params IFastBridgeBridgeParams) (*types.Transaction, error) { - return _FastBridge.Contract.Bridge(&_FastBridge.TransactOpts, params) +// Solidity: function REFUND_DELAY() view returns(uint256) +func (_FastBridge *FastBridgeCaller) REFUNDDELAY(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "REFUND_DELAY") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// Claim is a paid mutator transaction binding the contract method 0x41fcb612. +// REFUNDDELAY is a free data retrieval call binding the contract method 0x190da595. // -// Solidity: function claim(bytes request, address to) returns() -func (_FastBridge *FastBridgeTransactor) Claim(opts *bind.TransactOpts, request []byte, to common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "claim", request, to) +// Solidity: function REFUND_DELAY() view returns(uint256) +func (_FastBridge *FastBridgeSession) REFUNDDELAY() (*big.Int, error) { + return _FastBridge.Contract.REFUNDDELAY(&_FastBridge.CallOpts) } -// Claim is a paid mutator transaction binding the contract method 0x41fcb612. +// REFUNDDELAY is a free data retrieval call binding the contract method 0x190da595. // -// Solidity: function claim(bytes request, address to) returns() -func (_FastBridge *FastBridgeSession) Claim(request []byte, to common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.Claim(&_FastBridge.TransactOpts, request, to) +// Solidity: function REFUND_DELAY() view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) REFUNDDELAY() (*big.Int, error) { + return _FastBridge.Contract.REFUNDDELAY(&_FastBridge.CallOpts) } -// Claim is a paid mutator transaction binding the contract method 0x41fcb612. +// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. // -// Solidity: function claim(bytes request, address to) returns() -func (_FastBridge *FastBridgeTransactorSession) Claim(request []byte, to common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.Claim(&_FastBridge.TransactOpts, request, to) -} +// Solidity: function RELAYER_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCaller) RELAYERROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "RELAYER_ROLE") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err -// Dispute is a paid mutator transaction binding the contract method 0xadd98c70. -// -// Solidity: function dispute(bytes32 transactionId) returns() -func (_FastBridge *FastBridgeTransactor) Dispute(opts *bind.TransactOpts, transactionId [32]byte) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "dispute", transactionId) } -// Dispute is a paid mutator transaction binding the contract method 0xadd98c70. +// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. // -// Solidity: function dispute(bytes32 transactionId) returns() -func (_FastBridge *FastBridgeSession) Dispute(transactionId [32]byte) (*types.Transaction, error) { - return _FastBridge.Contract.Dispute(&_FastBridge.TransactOpts, transactionId) +// Solidity: function RELAYER_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeSession) RELAYERROLE() ([32]byte, error) { + return _FastBridge.Contract.RELAYERROLE(&_FastBridge.CallOpts) } -// Dispute is a paid mutator transaction binding the contract method 0xadd98c70. +// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. // -// Solidity: function dispute(bytes32 transactionId) returns() -func (_FastBridge *FastBridgeTransactorSession) Dispute(transactionId [32]byte) (*types.Transaction, error) { - return _FastBridge.Contract.Dispute(&_FastBridge.TransactOpts, transactionId) +// Solidity: function RELAYER_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCallerSession) RELAYERROLE() ([32]byte, error) { + return _FastBridge.Contract.RELAYERROLE(&_FastBridge.CallOpts) } -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// BridgeProofs is a free data retrieval call binding the contract method 0x91ad5039. // -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_FastBridge *FastBridgeTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "grantRole", role, account) +// Solidity: function bridgeProofs(bytes32 ) view returns(uint96 timestamp, address relayer) +func (_FastBridge *FastBridgeCaller) BridgeProofs(opts *bind.CallOpts, arg0 [32]byte) (struct { + Timestamp *big.Int + Relayer common.Address +}, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "bridgeProofs", arg0) + + outstruct := new(struct { + Timestamp *big.Int + Relayer common.Address + }) + if err != nil { + return *outstruct, err + } + + outstruct.Timestamp = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.Relayer = *abi.ConvertType(out[1], new(common.Address)).(*common.Address) + + return *outstruct, err + } -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// BridgeProofs is a free data retrieval call binding the contract method 0x91ad5039. // -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_FastBridge *FastBridgeSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.GrantRole(&_FastBridge.TransactOpts, role, account) +// Solidity: function bridgeProofs(bytes32 ) view returns(uint96 timestamp, address relayer) +func (_FastBridge *FastBridgeSession) BridgeProofs(arg0 [32]byte) (struct { + Timestamp *big.Int + Relayer common.Address +}, error) { + return _FastBridge.Contract.BridgeProofs(&_FastBridge.CallOpts, arg0) } -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// BridgeProofs is a free data retrieval call binding the contract method 0x91ad5039. // -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_FastBridge *FastBridgeTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.GrantRole(&_FastBridge.TransactOpts, role, account) +// Solidity: function bridgeProofs(bytes32 ) view returns(uint96 timestamp, address relayer) +func (_FastBridge *FastBridgeCallerSession) BridgeProofs(arg0 [32]byte) (struct { + Timestamp *big.Int + Relayer common.Address +}, error) { + return _FastBridge.Contract.BridgeProofs(&_FastBridge.CallOpts, arg0) } -// Prove is a paid mutator transaction binding the contract method 0x886d36ff. +// BridgeRelays is a free data retrieval call binding the contract method 0x8379a24f. // -// Solidity: function prove(bytes request, bytes32 destTxHash) returns() -func (_FastBridge *FastBridgeTransactor) Prove(opts *bind.TransactOpts, request []byte, destTxHash [32]byte) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "prove", request, destTxHash) +// Solidity: function bridgeRelays(bytes32 ) view returns(bool) +func (_FastBridge *FastBridgeCaller) BridgeRelays(opts *bind.CallOpts, arg0 [32]byte) (bool, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "bridgeRelays", arg0) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + } -// Prove is a paid mutator transaction binding the contract method 0x886d36ff. +// BridgeRelays is a free data retrieval call binding the contract method 0x8379a24f. // -// Solidity: function prove(bytes request, bytes32 destTxHash) returns() -func (_FastBridge *FastBridgeSession) Prove(request []byte, destTxHash [32]byte) (*types.Transaction, error) { - return _FastBridge.Contract.Prove(&_FastBridge.TransactOpts, request, destTxHash) +// Solidity: function bridgeRelays(bytes32 ) view returns(bool) +func (_FastBridge *FastBridgeSession) BridgeRelays(arg0 [32]byte) (bool, error) { + return _FastBridge.Contract.BridgeRelays(&_FastBridge.CallOpts, arg0) } -// Prove is a paid mutator transaction binding the contract method 0x886d36ff. +// BridgeRelays is a free data retrieval call binding the contract method 0x8379a24f. // -// Solidity: function prove(bytes request, bytes32 destTxHash) returns() -func (_FastBridge *FastBridgeTransactorSession) Prove(request []byte, destTxHash [32]byte) (*types.Transaction, error) { - return _FastBridge.Contract.Prove(&_FastBridge.TransactOpts, request, destTxHash) +// Solidity: function bridgeRelays(bytes32 ) view returns(bool) +func (_FastBridge *FastBridgeCallerSession) BridgeRelays(arg0 [32]byte) (bool, error) { + return _FastBridge.Contract.BridgeRelays(&_FastBridge.CallOpts, arg0) } -// Refund is a paid mutator transaction binding the contract method 0x5eb7d946. +// BridgeStatuses is a free data retrieval call binding the contract method 0x051287bc. // -// Solidity: function refund(bytes request) returns() -func (_FastBridge *FastBridgeTransactor) Refund(opts *bind.TransactOpts, request []byte) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "refund", request) +// Solidity: function bridgeStatuses(bytes32 ) view returns(uint8) +func (_FastBridge *FastBridgeCaller) BridgeStatuses(opts *bind.CallOpts, arg0 [32]byte) (uint8, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "bridgeStatuses", arg0) + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + } -// Refund is a paid mutator transaction binding the contract method 0x5eb7d946. +// BridgeStatuses is a free data retrieval call binding the contract method 0x051287bc. // -// Solidity: function refund(bytes request) returns() -func (_FastBridge *FastBridgeSession) Refund(request []byte) (*types.Transaction, error) { - return _FastBridge.Contract.Refund(&_FastBridge.TransactOpts, request) +// Solidity: function bridgeStatuses(bytes32 ) view returns(uint8) +func (_FastBridge *FastBridgeSession) BridgeStatuses(arg0 [32]byte) (uint8, error) { + return _FastBridge.Contract.BridgeStatuses(&_FastBridge.CallOpts, arg0) } -// Refund is a paid mutator transaction binding the contract method 0x5eb7d946. +// BridgeStatuses is a free data retrieval call binding the contract method 0x051287bc. // -// Solidity: function refund(bytes request) returns() -func (_FastBridge *FastBridgeTransactorSession) Refund(request []byte) (*types.Transaction, error) { - return _FastBridge.Contract.Refund(&_FastBridge.TransactOpts, request) +// Solidity: function bridgeStatuses(bytes32 ) view returns(uint8) +func (_FastBridge *FastBridgeCallerSession) BridgeStatuses(arg0 [32]byte) (uint8, error) { + return _FastBridge.Contract.BridgeStatuses(&_FastBridge.CallOpts, arg0) } -// Relay is a paid mutator transaction binding the contract method 0x8f0d6f17. +// CanClaim is a free data retrieval call binding the contract method 0xaa9641ab. // -// Solidity: function relay(bytes request) payable returns() -func (_FastBridge *FastBridgeTransactor) Relay(opts *bind.TransactOpts, request []byte) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "relay", request) +// Solidity: function canClaim(bytes32 transactionId, address relayer) view returns(bool) +func (_FastBridge *FastBridgeCaller) CanClaim(opts *bind.CallOpts, transactionId [32]byte, relayer common.Address) (bool, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "canClaim", transactionId, relayer) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + } -// Relay is a paid mutator transaction binding the contract method 0x8f0d6f17. +// CanClaim is a free data retrieval call binding the contract method 0xaa9641ab. // -// Solidity: function relay(bytes request) payable returns() -func (_FastBridge *FastBridgeSession) Relay(request []byte) (*types.Transaction, error) { - return _FastBridge.Contract.Relay(&_FastBridge.TransactOpts, request) +// Solidity: function canClaim(bytes32 transactionId, address relayer) view returns(bool) +func (_FastBridge *FastBridgeSession) CanClaim(transactionId [32]byte, relayer common.Address) (bool, error) { + return _FastBridge.Contract.CanClaim(&_FastBridge.CallOpts, transactionId, relayer) } -// Relay is a paid mutator transaction binding the contract method 0x8f0d6f17. +// CanClaim is a free data retrieval call binding the contract method 0xaa9641ab. // -// Solidity: function relay(bytes request) payable returns() -func (_FastBridge *FastBridgeTransactorSession) Relay(request []byte) (*types.Transaction, error) { - return _FastBridge.Contract.Relay(&_FastBridge.TransactOpts, request) +// Solidity: function canClaim(bytes32 transactionId, address relayer) view returns(bool) +func (_FastBridge *FastBridgeCallerSession) CanClaim(transactionId [32]byte, relayer common.Address) (bool, error) { + return _FastBridge.Contract.CanClaim(&_FastBridge.CallOpts, transactionId, relayer) } -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. +// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. // -// Solidity: function removeGovernor(address _governor) returns() -func (_FastBridge *FastBridgeTransactor) RemoveGovernor(opts *bind.TransactOpts, _governor common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "removeGovernor", _governor) +// Solidity: function chainGasAmount() view returns(uint256) +func (_FastBridge *FastBridgeCaller) ChainGasAmount(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "chainGasAmount") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. +// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. // -// Solidity: function removeGovernor(address _governor) returns() -func (_FastBridge *FastBridgeSession) RemoveGovernor(_governor common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RemoveGovernor(&_FastBridge.TransactOpts, _governor) +// Solidity: function chainGasAmount() view returns(uint256) +func (_FastBridge *FastBridgeSession) ChainGasAmount() (*big.Int, error) { + return _FastBridge.Contract.ChainGasAmount(&_FastBridge.CallOpts) } -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. +// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. // -// Solidity: function removeGovernor(address _governor) returns() -func (_FastBridge *FastBridgeTransactorSession) RemoveGovernor(_governor common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RemoveGovernor(&_FastBridge.TransactOpts, _governor) +// Solidity: function chainGasAmount() view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) ChainGasAmount() (*big.Int, error) { + return _FastBridge.Contract.ChainGasAmount(&_FastBridge.CallOpts) } -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. +// DeployBlock is a free data retrieval call binding the contract method 0xa3ec191a. // -// Solidity: function removeGuard(address _guard) returns() -func (_FastBridge *FastBridgeTransactor) RemoveGuard(opts *bind.TransactOpts, _guard common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "removeGuard", _guard) +// Solidity: function deployBlock() view returns(uint256) +func (_FastBridge *FastBridgeCaller) DeployBlock(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "deployBlock") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. +// DeployBlock is a free data retrieval call binding the contract method 0xa3ec191a. // -// Solidity: function removeGuard(address _guard) returns() -func (_FastBridge *FastBridgeSession) RemoveGuard(_guard common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RemoveGuard(&_FastBridge.TransactOpts, _guard) +// Solidity: function deployBlock() view returns(uint256) +func (_FastBridge *FastBridgeSession) DeployBlock() (*big.Int, error) { + return _FastBridge.Contract.DeployBlock(&_FastBridge.CallOpts) } -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. +// DeployBlock is a free data retrieval call binding the contract method 0xa3ec191a. // -// Solidity: function removeGuard(address _guard) returns() -func (_FastBridge *FastBridgeTransactorSession) RemoveGuard(_guard common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RemoveGuard(&_FastBridge.TransactOpts, _guard) +// Solidity: function deployBlock() view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) DeployBlock() (*big.Int, error) { + return _FastBridge.Contract.DeployBlock(&_FastBridge.CallOpts) } -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. +// GetBridgeTransaction is a free data retrieval call binding the contract method 0xac11fb1a. // -// Solidity: function removeRelayer(address _relayer) returns() -func (_FastBridge *FastBridgeTransactor) RemoveRelayer(opts *bind.TransactOpts, _relayer common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "removeRelayer", _relayer) +// Solidity: function getBridgeTransaction(bytes request) pure returns((uint32,uint32,address,address,address,address,uint256,uint256,uint256,bool,uint256,uint256)) +func (_FastBridge *FastBridgeCaller) GetBridgeTransaction(opts *bind.CallOpts, request []byte) (IFastBridgeBridgeTransaction, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "getBridgeTransaction", request) + + if err != nil { + return *new(IFastBridgeBridgeTransaction), err + } + + out0 := *abi.ConvertType(out[0], new(IFastBridgeBridgeTransaction)).(*IFastBridgeBridgeTransaction) + + return out0, err + } -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. +// GetBridgeTransaction is a free data retrieval call binding the contract method 0xac11fb1a. // -// Solidity: function removeRelayer(address _relayer) returns() -func (_FastBridge *FastBridgeSession) RemoveRelayer(_relayer common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RemoveRelayer(&_FastBridge.TransactOpts, _relayer) +// Solidity: function getBridgeTransaction(bytes request) pure returns((uint32,uint32,address,address,address,address,uint256,uint256,uint256,bool,uint256,uint256)) +func (_FastBridge *FastBridgeSession) GetBridgeTransaction(request []byte) (IFastBridgeBridgeTransaction, error) { + return _FastBridge.Contract.GetBridgeTransaction(&_FastBridge.CallOpts, request) } -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. +// GetBridgeTransaction is a free data retrieval call binding the contract method 0xac11fb1a. // -// Solidity: function removeRelayer(address _relayer) returns() -func (_FastBridge *FastBridgeTransactorSession) RemoveRelayer(_relayer common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RemoveRelayer(&_FastBridge.TransactOpts, _relayer) +// Solidity: function getBridgeTransaction(bytes request) pure returns((uint32,uint32,address,address,address,address,uint256,uint256,uint256,bool,uint256,uint256)) +func (_FastBridge *FastBridgeCallerSession) GetBridgeTransaction(request []byte) (IFastBridgeBridgeTransaction, error) { + return _FastBridge.Contract.GetBridgeTransaction(&_FastBridge.CallOpts, request) } -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. // -// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() -func (_FastBridge *FastBridgeTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "renounceRole", role, callerConfirmation) +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_FastBridge *FastBridgeCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "getRoleAdmin", role) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. // -// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() -func (_FastBridge *FastBridgeSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RenounceRole(&_FastBridge.TransactOpts, role, callerConfirmation) +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_FastBridge *FastBridgeSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _FastBridge.Contract.GetRoleAdmin(&_FastBridge.CallOpts, role) } -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. // -// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() -func (_FastBridge *FastBridgeTransactorSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RenounceRole(&_FastBridge.TransactOpts, role, callerConfirmation) +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_FastBridge *FastBridgeCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _FastBridge.Contract.GetRoleAdmin(&_FastBridge.CallOpts, role) } -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. // -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_FastBridge *FastBridgeTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "revokeRole", role, account) +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_FastBridge *FastBridgeCaller) GetRoleMember(opts *bind.CallOpts, role [32]byte, index *big.Int) (common.Address, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "getRoleMember", role, index) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + } -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. // -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_FastBridge *FastBridgeSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RevokeRole(&_FastBridge.TransactOpts, role, account) +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_FastBridge *FastBridgeSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _FastBridge.Contract.GetRoleMember(&_FastBridge.CallOpts, role, index) } -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. // -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_FastBridge *FastBridgeTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RevokeRole(&_FastBridge.TransactOpts, role, account) +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_FastBridge *FastBridgeCallerSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _FastBridge.Contract.GetRoleMember(&_FastBridge.CallOpts, role, index) } -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. // -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_FastBridge *FastBridgeTransactor) SetChainGasAmount(opts *bind.TransactOpts, newChainGasAmount *big.Int) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "setChainGasAmount", newChainGasAmount) +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_FastBridge *FastBridgeCaller) GetRoleMemberCount(opts *bind.CallOpts, role [32]byte) (*big.Int, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "getRoleMemberCount", role) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. // -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_FastBridge *FastBridgeSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { - return _FastBridge.Contract.SetChainGasAmount(&_FastBridge.TransactOpts, newChainGasAmount) +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_FastBridge *FastBridgeSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _FastBridge.Contract.GetRoleMemberCount(&_FastBridge.CallOpts, role) } -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. // -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_FastBridge *FastBridgeTransactorSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { - return _FastBridge.Contract.SetChainGasAmount(&_FastBridge.TransactOpts, newChainGasAmount) +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _FastBridge.Contract.GetRoleMemberCount(&_FastBridge.CallOpts, role) } -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. +// HasRole is a free data retrieval call binding the contract method 0x91d14854. // -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_FastBridge *FastBridgeTransactor) SetProtocolFeeRate(opts *bind.TransactOpts, newFeeRate *big.Int) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "setProtocolFeeRate", newFeeRate) +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_FastBridge *FastBridgeCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "hasRole", role, account) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + } -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. +// HasRole is a free data retrieval call binding the contract method 0x91d14854. // -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_FastBridge *FastBridgeSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { - return _FastBridge.Contract.SetProtocolFeeRate(&_FastBridge.TransactOpts, newFeeRate) +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_FastBridge *FastBridgeSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _FastBridge.Contract.HasRole(&_FastBridge.CallOpts, role, account) } -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. +// HasRole is a free data retrieval call binding the contract method 0x91d14854. // -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_FastBridge *FastBridgeTransactorSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { - return _FastBridge.Contract.SetProtocolFeeRate(&_FastBridge.TransactOpts, newFeeRate) +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_FastBridge *FastBridgeCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _FastBridge.Contract.HasRole(&_FastBridge.CallOpts, role, account) } -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. // -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_FastBridge *FastBridgeTransactor) SweepProtocolFees(opts *bind.TransactOpts, token common.Address, recipient common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "sweepProtocolFees", token, recipient) +// Solidity: function nonce() view returns(uint256) +func (_FastBridge *FastBridgeCaller) Nonce(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "nonce") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. // -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_FastBridge *FastBridgeSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.SweepProtocolFees(&_FastBridge.TransactOpts, token, recipient) +// Solidity: function nonce() view returns(uint256) +func (_FastBridge *FastBridgeSession) Nonce() (*big.Int, error) { + return _FastBridge.Contract.Nonce(&_FastBridge.CallOpts) } -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. // -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_FastBridge *FastBridgeTransactorSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.SweepProtocolFees(&_FastBridge.TransactOpts, token, recipient) +// Solidity: function nonce() view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) Nonce() (*big.Int, error) { + return _FastBridge.Contract.Nonce(&_FastBridge.CallOpts) } -// FastBridgeBridgeDepositClaimedIterator is returned from FilterBridgeDepositClaimed and is used to iterate over the raw logs and unpacked data for BridgeDepositClaimed events raised by the FastBridge contract. -type FastBridgeBridgeDepositClaimedIterator struct { - Event *FastBridgeBridgeDepositClaimed // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} +// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// +// Solidity: function protocolFeeRate() view returns(uint256) +func (_FastBridge *FastBridgeCaller) ProtocolFeeRate(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "protocolFeeRate") -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *FastBridgeBridgeDepositClaimedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false + if err != nil { + return *new(*big.Int), err } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(FastBridgeBridgeDepositClaimed) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(FastBridgeBridgeDepositClaimed) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} + return out0, err -// Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeBridgeDepositClaimedIterator) Error() error { - return it.fail } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *FastBridgeBridgeDepositClaimedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// +// Solidity: function protocolFeeRate() view returns(uint256) +func (_FastBridge *FastBridgeSession) ProtocolFeeRate() (*big.Int, error) { + return _FastBridge.Contract.ProtocolFeeRate(&_FastBridge.CallOpts) } -// FastBridgeBridgeDepositClaimed represents a BridgeDepositClaimed event raised by the FastBridge contract. -type FastBridgeBridgeDepositClaimed struct { - TransactionId [32]byte - Relayer common.Address - To common.Address - Token common.Address - Amount *big.Int - Raw types.Log // Blockchain specific contextual infos +// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// +// Solidity: function protocolFeeRate() view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) ProtocolFeeRate() (*big.Int, error) { + return _FastBridge.Contract.ProtocolFeeRate(&_FastBridge.CallOpts) } -// FilterBridgeDepositClaimed is a free log retrieval operation binding the contract event 0x582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac678. +// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. // -// Solidity: event BridgeDepositClaimed(bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount) -func (_FastBridge *FastBridgeFilterer) FilterBridgeDepositClaimed(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address, to []common.Address) (*FastBridgeBridgeDepositClaimedIterator, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } +// Solidity: function protocolFees(address ) view returns(uint256) +func (_FastBridge *FastBridgeCaller) ProtocolFees(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "protocolFees", arg0) - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeDepositClaimed", transactionIdRule, relayerRule, toRule) if err != nil { - return nil, err + return *new(*big.Int), err } - return &FastBridgeBridgeDepositClaimedIterator{contract: _FastBridge.contract, event: "BridgeDepositClaimed", logs: logs, sub: sub}, nil -} -// WatchBridgeDepositClaimed is a free log subscription operation binding the contract event 0x582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac678. -// -// Solidity: event BridgeDepositClaimed(bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount) -func (_FastBridge *FastBridgeFilterer) WatchBridgeDepositClaimed(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeDepositClaimed, transactionId [][32]byte, relayer []common.Address, to []common.Address) (event.Subscription, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeDepositClaimed", transactionIdRule, relayerRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(FastBridgeBridgeDepositClaimed) - if err := _FastBridge.contract.UnpackLog(event, "BridgeDepositClaimed", log); err != nil { - return err - } - event.Raw = log + return out0, err - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil } -// ParseBridgeDepositClaimed is a log parse operation binding the contract event 0x582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac678. +// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. // -// Solidity: event BridgeDepositClaimed(bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount) -func (_FastBridge *FastBridgeFilterer) ParseBridgeDepositClaimed(log types.Log) (*FastBridgeBridgeDepositClaimed, error) { - event := new(FastBridgeBridgeDepositClaimed) - if err := _FastBridge.contract.UnpackLog(event, "BridgeDepositClaimed", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function protocolFees(address ) view returns(uint256) +func (_FastBridge *FastBridgeSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { + return _FastBridge.Contract.ProtocolFees(&_FastBridge.CallOpts, arg0) } -// FastBridgeBridgeDepositRefundedIterator is returned from FilterBridgeDepositRefunded and is used to iterate over the raw logs and unpacked data for BridgeDepositRefunded events raised by the FastBridge contract. -type FastBridgeBridgeDepositRefundedIterator struct { - Event *FastBridgeBridgeDepositRefunded // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. +// +// Solidity: function protocolFees(address ) view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { + return _FastBridge.Contract.ProtocolFees(&_FastBridge.CallOpts, arg0) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *FastBridgeBridgeDepositRefundedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(FastBridgeBridgeDepositRefunded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_FastBridge *FastBridgeCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "supportsInterface", interfaceId) - default: - return false - } + if err != nil { + return *new(bool), err } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(FastBridgeBridgeDepositRefunded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err -// Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeBridgeDepositRefundedIterator) Error() error { - return it.fail } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *FastBridgeBridgeDepositRefundedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_FastBridge *FastBridgeSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _FastBridge.Contract.SupportsInterface(&_FastBridge.CallOpts, interfaceId) } -// FastBridgeBridgeDepositRefunded represents a BridgeDepositRefunded event raised by the FastBridge contract. -type FastBridgeBridgeDepositRefunded struct { - TransactionId [32]byte - To common.Address - Token common.Address - Amount *big.Int - Raw types.Log // Blockchain specific contextual infos +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_FastBridge *FastBridgeCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _FastBridge.Contract.SupportsInterface(&_FastBridge.CallOpts, interfaceId) } -// FilterBridgeDepositRefunded is a free log retrieval operation binding the contract event 0xb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958. +// Bridge is a paid mutator transaction binding the contract method 0x45851694. // -// Solidity: event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount) -func (_FastBridge *FastBridgeFilterer) FilterBridgeDepositRefunded(opts *bind.FilterOpts, transactionId [][32]byte, to []common.Address) (*FastBridgeBridgeDepositRefundedIterator, error) { +// Solidity: function bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256) params) payable returns() +func (_FastBridge *FastBridgeTransactor) Bridge(opts *bind.TransactOpts, params IFastBridgeBridgeParams) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "bridge", params) +} - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } +// Bridge is a paid mutator transaction binding the contract method 0x45851694. +// +// Solidity: function bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256) params) payable returns() +func (_FastBridge *FastBridgeSession) Bridge(params IFastBridgeBridgeParams) (*types.Transaction, error) { + return _FastBridge.Contract.Bridge(&_FastBridge.TransactOpts, params) +} - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeDepositRefunded", transactionIdRule, toRule) - if err != nil { - return nil, err - } - return &FastBridgeBridgeDepositRefundedIterator{contract: _FastBridge.contract, event: "BridgeDepositRefunded", logs: logs, sub: sub}, nil +// Bridge is a paid mutator transaction binding the contract method 0x45851694. +// +// Solidity: function bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256) params) payable returns() +func (_FastBridge *FastBridgeTransactorSession) Bridge(params IFastBridgeBridgeParams) (*types.Transaction, error) { + return _FastBridge.Contract.Bridge(&_FastBridge.TransactOpts, params) } -// WatchBridgeDepositRefunded is a free log subscription operation binding the contract event 0xb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958. +// Claim is a paid mutator transaction binding the contract method 0x41fcb612. // -// Solidity: event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount) -func (_FastBridge *FastBridgeFilterer) WatchBridgeDepositRefunded(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeDepositRefunded, transactionId [][32]byte, to []common.Address) (event.Subscription, error) { +// Solidity: function claim(bytes request, address to) returns() +func (_FastBridge *FastBridgeTransactor) Claim(opts *bind.TransactOpts, request []byte, to common.Address) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "claim", request, to) +} - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } +// Claim is a paid mutator transaction binding the contract method 0x41fcb612. +// +// Solidity: function claim(bytes request, address to) returns() +func (_FastBridge *FastBridgeSession) Claim(request []byte, to common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.Claim(&_FastBridge.TransactOpts, request, to) +} - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeDepositRefunded", transactionIdRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(FastBridgeBridgeDepositRefunded) - if err := _FastBridge.contract.UnpackLog(event, "BridgeDepositRefunded", log); err != nil { - return err - } - event.Raw = log +// Claim is a paid mutator transaction binding the contract method 0x41fcb612. +// +// Solidity: function claim(bytes request, address to) returns() +func (_FastBridge *FastBridgeTransactorSession) Claim(request []byte, to common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.Claim(&_FastBridge.TransactOpts, request, to) +} - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil +// Dispute is a paid mutator transaction binding the contract method 0xadd98c70. +// +// Solidity: function dispute(bytes32 transactionId) returns() +func (_FastBridge *FastBridgeTransactor) Dispute(opts *bind.TransactOpts, transactionId [32]byte) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "dispute", transactionId) } -// ParseBridgeDepositRefunded is a log parse operation binding the contract event 0xb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958. +// Dispute is a paid mutator transaction binding the contract method 0xadd98c70. // -// Solidity: event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount) -func (_FastBridge *FastBridgeFilterer) ParseBridgeDepositRefunded(log types.Log) (*FastBridgeBridgeDepositRefunded, error) { - event := new(FastBridgeBridgeDepositRefunded) - if err := _FastBridge.contract.UnpackLog(event, "BridgeDepositRefunded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function dispute(bytes32 transactionId) returns() +func (_FastBridge *FastBridgeSession) Dispute(transactionId [32]byte) (*types.Transaction, error) { + return _FastBridge.Contract.Dispute(&_FastBridge.TransactOpts, transactionId) } -// FastBridgeBridgeProofDisputedIterator is returned from FilterBridgeProofDisputed and is used to iterate over the raw logs and unpacked data for BridgeProofDisputed events raised by the FastBridge contract. -type FastBridgeBridgeProofDisputedIterator struct { - Event *FastBridgeBridgeProofDisputed // Event containing the contract specifics and raw log +// Dispute is a paid mutator transaction binding the contract method 0xadd98c70. +// +// Solidity: function dispute(bytes32 transactionId) returns() +func (_FastBridge *FastBridgeTransactorSession) Dispute(transactionId [32]byte) (*types.Transaction, error) { + return _FastBridge.Contract.Dispute(&_FastBridge.TransactOpts, transactionId) +} - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_FastBridge *FastBridgeTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "grantRole", role, account) +} - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_FastBridge *FastBridgeSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.GrantRole(&_FastBridge.TransactOpts, role, account) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *FastBridgeBridgeProofDisputedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(FastBridgeBridgeProofDisputed) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_FastBridge *FastBridgeTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.GrantRole(&_FastBridge.TransactOpts, role, account) +} - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(FastBridgeBridgeProofDisputed) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// Prove is a paid mutator transaction binding the contract method 0x886d36ff. +// +// Solidity: function prove(bytes request, bytes32 destTxHash) returns() +func (_FastBridge *FastBridgeTransactor) Prove(opts *bind.TransactOpts, request []byte, destTxHash [32]byte) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "prove", request, destTxHash) +} - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } +// Prove is a paid mutator transaction binding the contract method 0x886d36ff. +// +// Solidity: function prove(bytes request, bytes32 destTxHash) returns() +func (_FastBridge *FastBridgeSession) Prove(request []byte, destTxHash [32]byte) (*types.Transaction, error) { + return _FastBridge.Contract.Prove(&_FastBridge.TransactOpts, request, destTxHash) } -// Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeBridgeProofDisputedIterator) Error() error { - return it.fail +// Prove is a paid mutator transaction binding the contract method 0x886d36ff. +// +// Solidity: function prove(bytes request, bytes32 destTxHash) returns() +func (_FastBridge *FastBridgeTransactorSession) Prove(request []byte, destTxHash [32]byte) (*types.Transaction, error) { + return _FastBridge.Contract.Prove(&_FastBridge.TransactOpts, request, destTxHash) } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *FastBridgeBridgeProofDisputedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// Refund is a paid mutator transaction binding the contract method 0x5eb7d946. +// +// Solidity: function refund(bytes request) returns() +func (_FastBridge *FastBridgeTransactor) Refund(opts *bind.TransactOpts, request []byte) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "refund", request) } -// FastBridgeBridgeProofDisputed represents a BridgeProofDisputed event raised by the FastBridge contract. -type FastBridgeBridgeProofDisputed struct { - TransactionId [32]byte - Relayer common.Address - Raw types.Log // Blockchain specific contextual infos +// Refund is a paid mutator transaction binding the contract method 0x5eb7d946. +// +// Solidity: function refund(bytes request) returns() +func (_FastBridge *FastBridgeSession) Refund(request []byte) (*types.Transaction, error) { + return _FastBridge.Contract.Refund(&_FastBridge.TransactOpts, request) } -// FilterBridgeProofDisputed is a free log retrieval operation binding the contract event 0x0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad4. +// Refund is a paid mutator transaction binding the contract method 0x5eb7d946. // -// Solidity: event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer) -func (_FastBridge *FastBridgeFilterer) FilterBridgeProofDisputed(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address) (*FastBridgeBridgeProofDisputedIterator, error) { +// Solidity: function refund(bytes request) returns() +func (_FastBridge *FastBridgeTransactorSession) Refund(request []byte) (*types.Transaction, error) { + return _FastBridge.Contract.Refund(&_FastBridge.TransactOpts, request) +} - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } +// Relay is a paid mutator transaction binding the contract method 0x8f0d6f17. +// +// Solidity: function relay(bytes request) payable returns() +func (_FastBridge *FastBridgeTransactor) Relay(opts *bind.TransactOpts, request []byte) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "relay", request) +} - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeProofDisputed", transactionIdRule, relayerRule) - if err != nil { - return nil, err - } - return &FastBridgeBridgeProofDisputedIterator{contract: _FastBridge.contract, event: "BridgeProofDisputed", logs: logs, sub: sub}, nil +// Relay is a paid mutator transaction binding the contract method 0x8f0d6f17. +// +// Solidity: function relay(bytes request) payable returns() +func (_FastBridge *FastBridgeSession) Relay(request []byte) (*types.Transaction, error) { + return _FastBridge.Contract.Relay(&_FastBridge.TransactOpts, request) } -// WatchBridgeProofDisputed is a free log subscription operation binding the contract event 0x0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad4. +// Relay is a paid mutator transaction binding the contract method 0x8f0d6f17. // -// Solidity: event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer) -func (_FastBridge *FastBridgeFilterer) WatchBridgeProofDisputed(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeProofDisputed, transactionId [][32]byte, relayer []common.Address) (event.Subscription, error) { +// Solidity: function relay(bytes request) payable returns() +func (_FastBridge *FastBridgeTransactorSession) Relay(request []byte) (*types.Transaction, error) { + return _FastBridge.Contract.Relay(&_FastBridge.TransactOpts, request) +} - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_FastBridge *FastBridgeTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "renounceRole", role, callerConfirmation) +} - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeProofDisputed", transactionIdRule, relayerRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(FastBridgeBridgeProofDisputed) - if err := _FastBridge.contract.UnpackLog(event, "BridgeProofDisputed", log); err != nil { - return err - } - event.Raw = log +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_FastBridge *FastBridgeSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.RenounceRole(&_FastBridge.TransactOpts, role, callerConfirmation) +} - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_FastBridge *FastBridgeTransactorSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.RenounceRole(&_FastBridge.TransactOpts, role, callerConfirmation) } -// ParseBridgeProofDisputed is a log parse operation binding the contract event 0x0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad4. +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. // -// Solidity: event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer) -func (_FastBridge *FastBridgeFilterer) ParseBridgeProofDisputed(log types.Log) (*FastBridgeBridgeProofDisputed, error) { - event := new(FastBridgeBridgeProofDisputed) - if err := _FastBridge.contract.UnpackLog(event, "BridgeProofDisputed", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_FastBridge *FastBridgeTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "revokeRole", role, account) } -// FastBridgeBridgeProofProvidedIterator is returned from FilterBridgeProofProvided and is used to iterate over the raw logs and unpacked data for BridgeProofProvided events raised by the FastBridge contract. -type FastBridgeBridgeProofProvidedIterator struct { - Event *FastBridgeBridgeProofProvided // Event containing the contract specifics and raw log +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_FastBridge *FastBridgeSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.RevokeRole(&_FastBridge.TransactOpts, role, account) +} - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_FastBridge *FastBridgeTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.RevokeRole(&_FastBridge.TransactOpts, role, account) +} - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_FastBridge *FastBridgeTransactor) SetChainGasAmount(opts *bind.TransactOpts, newChainGasAmount *big.Int) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "setChainGasAmount", newChainGasAmount) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *FastBridgeBridgeProofProvidedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(FastBridgeBridgeProofProvided) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(FastBridgeBridgeProofProvided) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeBridgeProofProvidedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *FastBridgeBridgeProofProvidedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// FastBridgeBridgeProofProvided represents a BridgeProofProvided event raised by the FastBridge contract. -type FastBridgeBridgeProofProvided struct { - TransactionId [32]byte - Relayer common.Address - TransactionHash [32]byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterBridgeProofProvided is a free log retrieval operation binding the contract event 0x4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4. -// -// Solidity: event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash) -func (_FastBridge *FastBridgeFilterer) FilterBridgeProofProvided(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address) (*FastBridgeBridgeProofProvidedIterator, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeProofProvided", transactionIdRule, relayerRule) - if err != nil { - return nil, err - } - return &FastBridgeBridgeProofProvidedIterator{contract: _FastBridge.contract, event: "BridgeProofProvided", logs: logs, sub: sub}, nil -} - -// WatchBridgeProofProvided is a free log subscription operation binding the contract event 0x4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4. -// -// Solidity: event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash) -func (_FastBridge *FastBridgeFilterer) WatchBridgeProofProvided(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeProofProvided, transactionId [][32]byte, relayer []common.Address) (event.Subscription, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeProofProvided", transactionIdRule, relayerRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(FastBridgeBridgeProofProvided) - if err := _FastBridge.contract.UnpackLog(event, "BridgeProofProvided", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseBridgeProofProvided is a log parse operation binding the contract event 0x4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4. +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. // -// Solidity: event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash) -func (_FastBridge *FastBridgeFilterer) ParseBridgeProofProvided(log types.Log) (*FastBridgeBridgeProofProvided, error) { - event := new(FastBridgeBridgeProofProvided) - if err := _FastBridge.contract.UnpackLog(event, "BridgeProofProvided", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// FastBridgeBridgeRelayedIterator is returned from FilterBridgeRelayed and is used to iterate over the raw logs and unpacked data for BridgeRelayed events raised by the FastBridge contract. -type FastBridgeBridgeRelayedIterator struct { - Event *FastBridgeBridgeRelayed // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *FastBridgeBridgeRelayedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(FastBridgeBridgeRelayed) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(FastBridgeBridgeRelayed) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeBridgeRelayedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *FastBridgeBridgeRelayedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// FastBridgeBridgeRelayed represents a BridgeRelayed event raised by the FastBridge contract. -type FastBridgeBridgeRelayed struct { - TransactionId [32]byte - Relayer common.Address - To common.Address - OriginChainId uint32 - OriginToken common.Address - DestToken common.Address - OriginAmount *big.Int - DestAmount *big.Int - ChainGasAmount *big.Int - Raw types.Log // Blockchain specific contextual infos +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_FastBridge *FastBridgeSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { + return _FastBridge.Contract.SetChainGasAmount(&_FastBridge.TransactOpts, newChainGasAmount) } -// FilterBridgeRelayed is a free log retrieval operation binding the contract event 0xf8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c. +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. // -// Solidity: event BridgeRelayed(bytes32 indexed transactionId, address indexed relayer, address indexed to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) -func (_FastBridge *FastBridgeFilterer) FilterBridgeRelayed(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address, to []common.Address) (*FastBridgeBridgeRelayedIterator, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeRelayed", transactionIdRule, relayerRule, toRule) - if err != nil { - return nil, err - } - return &FastBridgeBridgeRelayedIterator{contract: _FastBridge.contract, event: "BridgeRelayed", logs: logs, sub: sub}, nil +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_FastBridge *FastBridgeTransactorSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { + return _FastBridge.Contract.SetChainGasAmount(&_FastBridge.TransactOpts, newChainGasAmount) } -// WatchBridgeRelayed is a free log subscription operation binding the contract event 0xf8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c. +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. // -// Solidity: event BridgeRelayed(bytes32 indexed transactionId, address indexed relayer, address indexed to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) -func (_FastBridge *FastBridgeFilterer) WatchBridgeRelayed(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeRelayed, transactionId [][32]byte, relayer []common.Address, to []common.Address) (event.Subscription, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeRelayed", transactionIdRule, relayerRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(FastBridgeBridgeRelayed) - if err := _FastBridge.contract.UnpackLog(event, "BridgeRelayed", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_FastBridge *FastBridgeTransactor) SetProtocolFeeRate(opts *bind.TransactOpts, newFeeRate *big.Int) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "setProtocolFeeRate", newFeeRate) } -// ParseBridgeRelayed is a log parse operation binding the contract event 0xf8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c. +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. // -// Solidity: event BridgeRelayed(bytes32 indexed transactionId, address indexed relayer, address indexed to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) -func (_FastBridge *FastBridgeFilterer) ParseBridgeRelayed(log types.Log) (*FastBridgeBridgeRelayed, error) { - event := new(FastBridgeBridgeRelayed) - if err := _FastBridge.contract.UnpackLog(event, "BridgeRelayed", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// FastBridgeBridgeRequestedIterator is returned from FilterBridgeRequested and is used to iterate over the raw logs and unpacked data for BridgeRequested events raised by the FastBridge contract. -type FastBridgeBridgeRequestedIterator struct { - Event *FastBridgeBridgeRequested // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *FastBridgeBridgeRequestedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(FastBridgeBridgeRequested) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(FastBridgeBridgeRequested) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeBridgeRequestedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *FastBridgeBridgeRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// FastBridgeBridgeRequested represents a BridgeRequested event raised by the FastBridge contract. -type FastBridgeBridgeRequested struct { - TransactionId [32]byte - Sender common.Address - Request []byte - DestChainId uint32 - OriginToken common.Address - DestToken common.Address - OriginAmount *big.Int - DestAmount *big.Int - SendChainGas bool - Raw types.Log // Blockchain specific contextual infos +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_FastBridge *FastBridgeSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { + return _FastBridge.Contract.SetProtocolFeeRate(&_FastBridge.TransactOpts, newFeeRate) } -// FilterBridgeRequested is a free log retrieval operation binding the contract event 0x120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a. +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. // -// Solidity: event BridgeRequested(bytes32 indexed transactionId, address indexed sender, bytes request, uint32 destChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, bool sendChainGas) -func (_FastBridge *FastBridgeFilterer) FilterBridgeRequested(opts *bind.FilterOpts, transactionId [][32]byte, sender []common.Address) (*FastBridgeBridgeRequestedIterator, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeRequested", transactionIdRule, senderRule) - if err != nil { - return nil, err - } - return &FastBridgeBridgeRequestedIterator{contract: _FastBridge.contract, event: "BridgeRequested", logs: logs, sub: sub}, nil +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_FastBridge *FastBridgeTransactorSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { + return _FastBridge.Contract.SetProtocolFeeRate(&_FastBridge.TransactOpts, newFeeRate) } -// WatchBridgeRequested is a free log subscription operation binding the contract event 0x120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a. +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. // -// Solidity: event BridgeRequested(bytes32 indexed transactionId, address indexed sender, bytes request, uint32 destChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, bool sendChainGas) -func (_FastBridge *FastBridgeFilterer) WatchBridgeRequested(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeRequested, transactionId [][32]byte, sender []common.Address) (event.Subscription, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeRequested", transactionIdRule, senderRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(FastBridgeBridgeRequested) - if err := _FastBridge.contract.UnpackLog(event, "BridgeRequested", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_FastBridge *FastBridgeTransactor) SweepProtocolFees(opts *bind.TransactOpts, token common.Address, recipient common.Address) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "sweepProtocolFees", token, recipient) } -// ParseBridgeRequested is a log parse operation binding the contract event 0x120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a. +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. // -// Solidity: event BridgeRequested(bytes32 indexed transactionId, address indexed sender, bytes request, uint32 destChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, bool sendChainGas) -func (_FastBridge *FastBridgeFilterer) ParseBridgeRequested(log types.Log) (*FastBridgeBridgeRequested, error) { - event := new(FastBridgeBridgeRequested) - if err := _FastBridge.contract.UnpackLog(event, "BridgeRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_FastBridge *FastBridgeSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.SweepProtocolFees(&_FastBridge.TransactOpts, token, recipient) } -// FastBridgeChainGasAmountUpdatedIterator is returned from FilterChainGasAmountUpdated and is used to iterate over the raw logs and unpacked data for ChainGasAmountUpdated events raised by the FastBridge contract. -type FastBridgeChainGasAmountUpdatedIterator struct { - Event *FastBridgeChainGasAmountUpdated // Event containing the contract specifics and raw log +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_FastBridge *FastBridgeTransactorSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.SweepProtocolFees(&_FastBridge.TransactOpts, token, recipient) +} + +// FastBridgeBridgeDepositClaimedIterator is returned from FilterBridgeDepositClaimed and is used to iterate over the raw logs and unpacked data for BridgeDepositClaimed events raised by the FastBridge contract. +type FastBridgeBridgeDepositClaimedIterator struct { + Event *FastBridgeBridgeDepositClaimed // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -6194,7 +5438,7 @@ type FastBridgeChainGasAmountUpdatedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeChainGasAmountUpdatedIterator) Next() bool { +func (it *FastBridgeBridgeDepositClaimedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -6203,7 +5447,7 @@ func (it *FastBridgeChainGasAmountUpdatedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeChainGasAmountUpdated) + it.Event = new(FastBridgeBridgeDepositClaimed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6218,7 +5462,7 @@ func (it *FastBridgeChainGasAmountUpdatedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeChainGasAmountUpdated) + it.Event = new(FastBridgeBridgeDepositClaimed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6234,42 +5478,71 @@ func (it *FastBridgeChainGasAmountUpdatedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeChainGasAmountUpdatedIterator) Error() error { +func (it *FastBridgeBridgeDepositClaimedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeChainGasAmountUpdatedIterator) Close() error { +func (it *FastBridgeBridgeDepositClaimedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeChainGasAmountUpdated represents a ChainGasAmountUpdated event raised by the FastBridge contract. -type FastBridgeChainGasAmountUpdated struct { - OldChainGasAmount *big.Int - NewChainGasAmount *big.Int - Raw types.Log // Blockchain specific contextual infos +// FastBridgeBridgeDepositClaimed represents a BridgeDepositClaimed event raised by the FastBridge contract. +type FastBridgeBridgeDepositClaimed struct { + TransactionId [32]byte + Relayer common.Address + To common.Address + Token common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterChainGasAmountUpdated is a free log retrieval operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. +// FilterBridgeDepositClaimed is a free log retrieval operation binding the contract event 0x582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac678. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_FastBridge *FastBridgeFilterer) FilterChainGasAmountUpdated(opts *bind.FilterOpts) (*FastBridgeChainGasAmountUpdatedIterator, error) { +// Solidity: event BridgeDepositClaimed(bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount) +func (_FastBridge *FastBridgeFilterer) FilterBridgeDepositClaimed(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address, to []common.Address) (*FastBridgeBridgeDepositClaimedIterator, error) { - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "ChainGasAmountUpdated") + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeDepositClaimed", transactionIdRule, relayerRule, toRule) if err != nil { return nil, err } - return &FastBridgeChainGasAmountUpdatedIterator{contract: _FastBridge.contract, event: "ChainGasAmountUpdated", logs: logs, sub: sub}, nil + return &FastBridgeBridgeDepositClaimedIterator{contract: _FastBridge.contract, event: "BridgeDepositClaimed", logs: logs, sub: sub}, nil } -// WatchChainGasAmountUpdated is a free log subscription operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. +// WatchBridgeDepositClaimed is a free log subscription operation binding the contract event 0x582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac678. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_FastBridge *FastBridgeFilterer) WatchChainGasAmountUpdated(opts *bind.WatchOpts, sink chan<- *FastBridgeChainGasAmountUpdated) (event.Subscription, error) { +// Solidity: event BridgeDepositClaimed(bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount) +func (_FastBridge *FastBridgeFilterer) WatchBridgeDepositClaimed(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeDepositClaimed, transactionId [][32]byte, relayer []common.Address, to []common.Address) (event.Subscription, error) { - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "ChainGasAmountUpdated") + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeDepositClaimed", transactionIdRule, relayerRule, toRule) if err != nil { return nil, err } @@ -6279,8 +5552,8 @@ func (_FastBridge *FastBridgeFilterer) WatchChainGasAmountUpdated(opts *bind.Wat select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeChainGasAmountUpdated) - if err := _FastBridge.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { + event := new(FastBridgeBridgeDepositClaimed) + if err := _FastBridge.contract.UnpackLog(event, "BridgeDepositClaimed", log); err != nil { return err } event.Raw = log @@ -6301,21 +5574,21 @@ func (_FastBridge *FastBridgeFilterer) WatchChainGasAmountUpdated(opts *bind.Wat }), nil } -// ParseChainGasAmountUpdated is a log parse operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. +// ParseBridgeDepositClaimed is a log parse operation binding the contract event 0x582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac678. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_FastBridge *FastBridgeFilterer) ParseChainGasAmountUpdated(log types.Log) (*FastBridgeChainGasAmountUpdated, error) { - event := new(FastBridgeChainGasAmountUpdated) - if err := _FastBridge.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { +// Solidity: event BridgeDepositClaimed(bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount) +func (_FastBridge *FastBridgeFilterer) ParseBridgeDepositClaimed(log types.Log) (*FastBridgeBridgeDepositClaimed, error) { + event := new(FastBridgeBridgeDepositClaimed) + if err := _FastBridge.contract.UnpackLog(event, "BridgeDepositClaimed", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeFeeRateUpdatedIterator is returned from FilterFeeRateUpdated and is used to iterate over the raw logs and unpacked data for FeeRateUpdated events raised by the FastBridge contract. -type FastBridgeFeeRateUpdatedIterator struct { - Event *FastBridgeFeeRateUpdated // Event containing the contract specifics and raw log +// FastBridgeBridgeDepositRefundedIterator is returned from FilterBridgeDepositRefunded and is used to iterate over the raw logs and unpacked data for BridgeDepositRefunded events raised by the FastBridge contract. +type FastBridgeBridgeDepositRefundedIterator struct { + Event *FastBridgeBridgeDepositRefunded // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -6329,7 +5602,7 @@ type FastBridgeFeeRateUpdatedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeFeeRateUpdatedIterator) Next() bool { +func (it *FastBridgeBridgeDepositRefundedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -6338,7 +5611,7 @@ func (it *FastBridgeFeeRateUpdatedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeFeeRateUpdated) + it.Event = new(FastBridgeBridgeDepositRefunded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6353,7 +5626,7 @@ func (it *FastBridgeFeeRateUpdatedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeFeeRateUpdated) + it.Event = new(FastBridgeBridgeDepositRefunded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6369,42 +5642,62 @@ func (it *FastBridgeFeeRateUpdatedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeFeeRateUpdatedIterator) Error() error { +func (it *FastBridgeBridgeDepositRefundedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeFeeRateUpdatedIterator) Close() error { +func (it *FastBridgeBridgeDepositRefundedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeFeeRateUpdated represents a FeeRateUpdated event raised by the FastBridge contract. -type FastBridgeFeeRateUpdated struct { - OldFeeRate *big.Int - NewFeeRate *big.Int - Raw types.Log // Blockchain specific contextual infos +// FastBridgeBridgeDepositRefunded represents a BridgeDepositRefunded event raised by the FastBridge contract. +type FastBridgeBridgeDepositRefunded struct { + TransactionId [32]byte + To common.Address + Token common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterFeeRateUpdated is a free log retrieval operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// FilterBridgeDepositRefunded is a free log retrieval operation binding the contract event 0xb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958. // -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_FastBridge *FastBridgeFilterer) FilterFeeRateUpdated(opts *bind.FilterOpts) (*FastBridgeFeeRateUpdatedIterator, error) { +// Solidity: event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount) +func (_FastBridge *FastBridgeFilterer) FilterBridgeDepositRefunded(opts *bind.FilterOpts, transactionId [][32]byte, to []common.Address) (*FastBridgeBridgeDepositRefundedIterator, error) { - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "FeeRateUpdated") + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeDepositRefunded", transactionIdRule, toRule) if err != nil { return nil, err } - return &FastBridgeFeeRateUpdatedIterator{contract: _FastBridge.contract, event: "FeeRateUpdated", logs: logs, sub: sub}, nil + return &FastBridgeBridgeDepositRefundedIterator{contract: _FastBridge.contract, event: "BridgeDepositRefunded", logs: logs, sub: sub}, nil } -// WatchFeeRateUpdated is a free log subscription operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// WatchBridgeDepositRefunded is a free log subscription operation binding the contract event 0xb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958. // -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_FastBridge *FastBridgeFilterer) WatchFeeRateUpdated(opts *bind.WatchOpts, sink chan<- *FastBridgeFeeRateUpdated) (event.Subscription, error) { +// Solidity: event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount) +func (_FastBridge *FastBridgeFilterer) WatchBridgeDepositRefunded(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeDepositRefunded, transactionId [][32]byte, to []common.Address) (event.Subscription, error) { - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "FeeRateUpdated") + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeDepositRefunded", transactionIdRule, toRule) if err != nil { return nil, err } @@ -6414,8 +5707,8 @@ func (_FastBridge *FastBridgeFilterer) WatchFeeRateUpdated(opts *bind.WatchOpts, select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeFeeRateUpdated) - if err := _FastBridge.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { + event := new(FastBridgeBridgeDepositRefunded) + if err := _FastBridge.contract.UnpackLog(event, "BridgeDepositRefunded", log); err != nil { return err } event.Raw = log @@ -6436,21 +5729,21 @@ func (_FastBridge *FastBridgeFilterer) WatchFeeRateUpdated(opts *bind.WatchOpts, }), nil } -// ParseFeeRateUpdated is a log parse operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// ParseBridgeDepositRefunded is a log parse operation binding the contract event 0xb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958. // -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_FastBridge *FastBridgeFilterer) ParseFeeRateUpdated(log types.Log) (*FastBridgeFeeRateUpdated, error) { - event := new(FastBridgeFeeRateUpdated) - if err := _FastBridge.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { +// Solidity: event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount) +func (_FastBridge *FastBridgeFilterer) ParseBridgeDepositRefunded(log types.Log) (*FastBridgeBridgeDepositRefunded, error) { + event := new(FastBridgeBridgeDepositRefunded) + if err := _FastBridge.contract.UnpackLog(event, "BridgeDepositRefunded", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeFeesSweptIterator is returned from FilterFeesSwept and is used to iterate over the raw logs and unpacked data for FeesSwept events raised by the FastBridge contract. -type FastBridgeFeesSweptIterator struct { - Event *FastBridgeFeesSwept // Event containing the contract specifics and raw log +// FastBridgeBridgeProofDisputedIterator is returned from FilterBridgeProofDisputed and is used to iterate over the raw logs and unpacked data for BridgeProofDisputed events raised by the FastBridge contract. +type FastBridgeBridgeProofDisputedIterator struct { + Event *FastBridgeBridgeProofDisputed // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -6464,7 +5757,7 @@ type FastBridgeFeesSweptIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeFeesSweptIterator) Next() bool { +func (it *FastBridgeBridgeProofDisputedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -6473,7 +5766,7 @@ func (it *FastBridgeFeesSweptIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeFeesSwept) + it.Event = new(FastBridgeBridgeProofDisputed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6488,7 +5781,7 @@ func (it *FastBridgeFeesSweptIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeFeesSwept) + it.Event = new(FastBridgeBridgeProofDisputed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6504,43 +5797,60 @@ func (it *FastBridgeFeesSweptIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeFeesSweptIterator) Error() error { +func (it *FastBridgeBridgeProofDisputedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeFeesSweptIterator) Close() error { +func (it *FastBridgeBridgeProofDisputedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeFeesSwept represents a FeesSwept event raised by the FastBridge contract. -type FastBridgeFeesSwept struct { - Token common.Address - Recipient common.Address - Amount *big.Int - Raw types.Log // Blockchain specific contextual infos +// FastBridgeBridgeProofDisputed represents a BridgeProofDisputed event raised by the FastBridge contract. +type FastBridgeBridgeProofDisputed struct { + TransactionId [32]byte + Relayer common.Address + Raw types.Log // Blockchain specific contextual infos } -// FilterFeesSwept is a free log retrieval operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// FilterBridgeProofDisputed is a free log retrieval operation binding the contract event 0x0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad4. // -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_FastBridge *FastBridgeFilterer) FilterFeesSwept(opts *bind.FilterOpts) (*FastBridgeFeesSweptIterator, error) { +// Solidity: event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer) +func (_FastBridge *FastBridgeFilterer) FilterBridgeProofDisputed(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address) (*FastBridgeBridgeProofDisputedIterator, error) { - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "FeesSwept") + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeProofDisputed", transactionIdRule, relayerRule) if err != nil { return nil, err } - return &FastBridgeFeesSweptIterator{contract: _FastBridge.contract, event: "FeesSwept", logs: logs, sub: sub}, nil + return &FastBridgeBridgeProofDisputedIterator{contract: _FastBridge.contract, event: "BridgeProofDisputed", logs: logs, sub: sub}, nil } -// WatchFeesSwept is a free log subscription operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// WatchBridgeProofDisputed is a free log subscription operation binding the contract event 0x0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad4. // -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_FastBridge *FastBridgeFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink chan<- *FastBridgeFeesSwept) (event.Subscription, error) { +// Solidity: event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer) +func (_FastBridge *FastBridgeFilterer) WatchBridgeProofDisputed(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeProofDisputed, transactionId [][32]byte, relayer []common.Address) (event.Subscription, error) { - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "FeesSwept") + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeProofDisputed", transactionIdRule, relayerRule) if err != nil { return nil, err } @@ -6550,8 +5860,8 @@ func (_FastBridge *FastBridgeFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeFeesSwept) - if err := _FastBridge.contract.UnpackLog(event, "FeesSwept", log); err != nil { + event := new(FastBridgeBridgeProofDisputed) + if err := _FastBridge.contract.UnpackLog(event, "BridgeProofDisputed", log); err != nil { return err } event.Raw = log @@ -6572,21 +5882,21 @@ func (_FastBridge *FastBridgeFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink }), nil } -// ParseFeesSwept is a log parse operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// ParseBridgeProofDisputed is a log parse operation binding the contract event 0x0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad4. // -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_FastBridge *FastBridgeFilterer) ParseFeesSwept(log types.Log) (*FastBridgeFeesSwept, error) { - event := new(FastBridgeFeesSwept) - if err := _FastBridge.contract.UnpackLog(event, "FeesSwept", log); err != nil { +// Solidity: event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer) +func (_FastBridge *FastBridgeFilterer) ParseBridgeProofDisputed(log types.Log) (*FastBridgeBridgeProofDisputed, error) { + event := new(FastBridgeBridgeProofDisputed) + if err := _FastBridge.contract.UnpackLog(event, "BridgeProofDisputed", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeGovernorAddedIterator is returned from FilterGovernorAdded and is used to iterate over the raw logs and unpacked data for GovernorAdded events raised by the FastBridge contract. -type FastBridgeGovernorAddedIterator struct { - Event *FastBridgeGovernorAdded // Event containing the contract specifics and raw log +// FastBridgeBridgeProofProvidedIterator is returned from FilterBridgeProofProvided and is used to iterate over the raw logs and unpacked data for BridgeProofProvided events raised by the FastBridge contract. +type FastBridgeBridgeProofProvidedIterator struct { + Event *FastBridgeBridgeProofProvided // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -6600,7 +5910,7 @@ type FastBridgeGovernorAddedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeGovernorAddedIterator) Next() bool { +func (it *FastBridgeBridgeProofProvidedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -6609,7 +5919,7 @@ func (it *FastBridgeGovernorAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeGovernorAdded) + it.Event = new(FastBridgeBridgeProofProvided) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6624,7 +5934,7 @@ func (it *FastBridgeGovernorAddedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeGovernorAdded) + it.Event = new(FastBridgeBridgeProofProvided) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6640,41 +5950,61 @@ func (it *FastBridgeGovernorAddedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeGovernorAddedIterator) Error() error { +func (it *FastBridgeBridgeProofProvidedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeGovernorAddedIterator) Close() error { +func (it *FastBridgeBridgeProofProvidedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeGovernorAdded represents a GovernorAdded event raised by the FastBridge contract. -type FastBridgeGovernorAdded struct { - Governor common.Address - Raw types.Log // Blockchain specific contextual infos +// FastBridgeBridgeProofProvided represents a BridgeProofProvided event raised by the FastBridge contract. +type FastBridgeBridgeProofProvided struct { + TransactionId [32]byte + Relayer common.Address + TransactionHash [32]byte + Raw types.Log // Blockchain specific contextual infos } -// FilterGovernorAdded is a free log retrieval operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. +// FilterBridgeProofProvided is a free log retrieval operation binding the contract event 0x4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4. // -// Solidity: event GovernorAdded(address governor) -func (_FastBridge *FastBridgeFilterer) FilterGovernorAdded(opts *bind.FilterOpts) (*FastBridgeGovernorAddedIterator, error) { +// Solidity: event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash) +func (_FastBridge *FastBridgeFilterer) FilterBridgeProofProvided(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address) (*FastBridgeBridgeProofProvidedIterator, error) { + + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "GovernorAdded") + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeProofProvided", transactionIdRule, relayerRule) if err != nil { return nil, err } - return &FastBridgeGovernorAddedIterator{contract: _FastBridge.contract, event: "GovernorAdded", logs: logs, sub: sub}, nil + return &FastBridgeBridgeProofProvidedIterator{contract: _FastBridge.contract, event: "BridgeProofProvided", logs: logs, sub: sub}, nil } -// WatchGovernorAdded is a free log subscription operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. +// WatchBridgeProofProvided is a free log subscription operation binding the contract event 0x4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4. // -// Solidity: event GovernorAdded(address governor) -func (_FastBridge *FastBridgeFilterer) WatchGovernorAdded(opts *bind.WatchOpts, sink chan<- *FastBridgeGovernorAdded) (event.Subscription, error) { +// Solidity: event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash) +func (_FastBridge *FastBridgeFilterer) WatchBridgeProofProvided(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeProofProvided, transactionId [][32]byte, relayer []common.Address) (event.Subscription, error) { + + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "GovernorAdded") + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeProofProvided", transactionIdRule, relayerRule) if err != nil { return nil, err } @@ -6684,8 +6014,8 @@ func (_FastBridge *FastBridgeFilterer) WatchGovernorAdded(opts *bind.WatchOpts, select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeGovernorAdded) - if err := _FastBridge.contract.UnpackLog(event, "GovernorAdded", log); err != nil { + event := new(FastBridgeBridgeProofProvided) + if err := _FastBridge.contract.UnpackLog(event, "BridgeProofProvided", log); err != nil { return err } event.Raw = log @@ -6706,21 +6036,21 @@ func (_FastBridge *FastBridgeFilterer) WatchGovernorAdded(opts *bind.WatchOpts, }), nil } -// ParseGovernorAdded is a log parse operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. +// ParseBridgeProofProvided is a log parse operation binding the contract event 0x4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4. // -// Solidity: event GovernorAdded(address governor) -func (_FastBridge *FastBridgeFilterer) ParseGovernorAdded(log types.Log) (*FastBridgeGovernorAdded, error) { - event := new(FastBridgeGovernorAdded) - if err := _FastBridge.contract.UnpackLog(event, "GovernorAdded", log); err != nil { +// Solidity: event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash) +func (_FastBridge *FastBridgeFilterer) ParseBridgeProofProvided(log types.Log) (*FastBridgeBridgeProofProvided, error) { + event := new(FastBridgeBridgeProofProvided) + if err := _FastBridge.contract.UnpackLog(event, "BridgeProofProvided", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeGovernorRemovedIterator is returned from FilterGovernorRemoved and is used to iterate over the raw logs and unpacked data for GovernorRemoved events raised by the FastBridge contract. -type FastBridgeGovernorRemovedIterator struct { - Event *FastBridgeGovernorRemoved // Event containing the contract specifics and raw log +// FastBridgeBridgeRelayedIterator is returned from FilterBridgeRelayed and is used to iterate over the raw logs and unpacked data for BridgeRelayed events raised by the FastBridge contract. +type FastBridgeBridgeRelayedIterator struct { + Event *FastBridgeBridgeRelayed // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -6734,7 +6064,7 @@ type FastBridgeGovernorRemovedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeGovernorRemovedIterator) Next() bool { +func (it *FastBridgeBridgeRelayedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -6743,7 +6073,7 @@ func (it *FastBridgeGovernorRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeGovernorRemoved) + it.Event = new(FastBridgeBridgeRelayed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6758,7 +6088,7 @@ func (it *FastBridgeGovernorRemovedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeGovernorRemoved) + it.Event = new(FastBridgeBridgeRelayed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6774,41 +6104,75 @@ func (it *FastBridgeGovernorRemovedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeGovernorRemovedIterator) Error() error { +func (it *FastBridgeBridgeRelayedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeGovernorRemovedIterator) Close() error { +func (it *FastBridgeBridgeRelayedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeGovernorRemoved represents a GovernorRemoved event raised by the FastBridge contract. -type FastBridgeGovernorRemoved struct { - Governor common.Address - Raw types.Log // Blockchain specific contextual infos +// FastBridgeBridgeRelayed represents a BridgeRelayed event raised by the FastBridge contract. +type FastBridgeBridgeRelayed struct { + TransactionId [32]byte + Relayer common.Address + To common.Address + OriginChainId uint32 + OriginToken common.Address + DestToken common.Address + OriginAmount *big.Int + DestAmount *big.Int + ChainGasAmount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterGovernorRemoved is a free log retrieval operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. +// FilterBridgeRelayed is a free log retrieval operation binding the contract event 0xf8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c. // -// Solidity: event GovernorRemoved(address governor) -func (_FastBridge *FastBridgeFilterer) FilterGovernorRemoved(opts *bind.FilterOpts) (*FastBridgeGovernorRemovedIterator, error) { +// Solidity: event BridgeRelayed(bytes32 indexed transactionId, address indexed relayer, address indexed to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) +func (_FastBridge *FastBridgeFilterer) FilterBridgeRelayed(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address, to []common.Address) (*FastBridgeBridgeRelayedIterator, error) { - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "GovernorRemoved") + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeRelayed", transactionIdRule, relayerRule, toRule) if err != nil { return nil, err } - return &FastBridgeGovernorRemovedIterator{contract: _FastBridge.contract, event: "GovernorRemoved", logs: logs, sub: sub}, nil + return &FastBridgeBridgeRelayedIterator{contract: _FastBridge.contract, event: "BridgeRelayed", logs: logs, sub: sub}, nil } -// WatchGovernorRemoved is a free log subscription operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. +// WatchBridgeRelayed is a free log subscription operation binding the contract event 0xf8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c. // -// Solidity: event GovernorRemoved(address governor) -func (_FastBridge *FastBridgeFilterer) WatchGovernorRemoved(opts *bind.WatchOpts, sink chan<- *FastBridgeGovernorRemoved) (event.Subscription, error) { +// Solidity: event BridgeRelayed(bytes32 indexed transactionId, address indexed relayer, address indexed to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) +func (_FastBridge *FastBridgeFilterer) WatchBridgeRelayed(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeRelayed, transactionId [][32]byte, relayer []common.Address, to []common.Address) (event.Subscription, error) { + + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "GovernorRemoved") + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeRelayed", transactionIdRule, relayerRule, toRule) if err != nil { return nil, err } @@ -6818,8 +6182,8 @@ func (_FastBridge *FastBridgeFilterer) WatchGovernorRemoved(opts *bind.WatchOpts select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeGovernorRemoved) - if err := _FastBridge.contract.UnpackLog(event, "GovernorRemoved", log); err != nil { + event := new(FastBridgeBridgeRelayed) + if err := _FastBridge.contract.UnpackLog(event, "BridgeRelayed", log); err != nil { return err } event.Raw = log @@ -6840,21 +6204,21 @@ func (_FastBridge *FastBridgeFilterer) WatchGovernorRemoved(opts *bind.WatchOpts }), nil } -// ParseGovernorRemoved is a log parse operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. +// ParseBridgeRelayed is a log parse operation binding the contract event 0xf8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c. // -// Solidity: event GovernorRemoved(address governor) -func (_FastBridge *FastBridgeFilterer) ParseGovernorRemoved(log types.Log) (*FastBridgeGovernorRemoved, error) { - event := new(FastBridgeGovernorRemoved) - if err := _FastBridge.contract.UnpackLog(event, "GovernorRemoved", log); err != nil { +// Solidity: event BridgeRelayed(bytes32 indexed transactionId, address indexed relayer, address indexed to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) +func (_FastBridge *FastBridgeFilterer) ParseBridgeRelayed(log types.Log) (*FastBridgeBridgeRelayed, error) { + event := new(FastBridgeBridgeRelayed) + if err := _FastBridge.contract.UnpackLog(event, "BridgeRelayed", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeGuardAddedIterator is returned from FilterGuardAdded and is used to iterate over the raw logs and unpacked data for GuardAdded events raised by the FastBridge contract. -type FastBridgeGuardAddedIterator struct { - Event *FastBridgeGuardAdded // Event containing the contract specifics and raw log +// FastBridgeBridgeRequestedIterator is returned from FilterBridgeRequested and is used to iterate over the raw logs and unpacked data for BridgeRequested events raised by the FastBridge contract. +type FastBridgeBridgeRequestedIterator struct { + Event *FastBridgeBridgeRequested // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -6868,7 +6232,7 @@ type FastBridgeGuardAddedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeGuardAddedIterator) Next() bool { +func (it *FastBridgeBridgeRequestedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -6877,7 +6241,7 @@ func (it *FastBridgeGuardAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeGuardAdded) + it.Event = new(FastBridgeBridgeRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6892,7 +6256,7 @@ func (it *FastBridgeGuardAddedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeGuardAdded) + it.Event = new(FastBridgeBridgeRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6908,41 +6272,67 @@ func (it *FastBridgeGuardAddedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeGuardAddedIterator) Error() error { +func (it *FastBridgeBridgeRequestedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeGuardAddedIterator) Close() error { +func (it *FastBridgeBridgeRequestedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeGuardAdded represents a GuardAdded event raised by the FastBridge contract. -type FastBridgeGuardAdded struct { - Guard common.Address - Raw types.Log // Blockchain specific contextual infos +// FastBridgeBridgeRequested represents a BridgeRequested event raised by the FastBridge contract. +type FastBridgeBridgeRequested struct { + TransactionId [32]byte + Sender common.Address + Request []byte + DestChainId uint32 + OriginToken common.Address + DestToken common.Address + OriginAmount *big.Int + DestAmount *big.Int + SendChainGas bool + Raw types.Log // Blockchain specific contextual infos } -// FilterGuardAdded is a free log retrieval operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// FilterBridgeRequested is a free log retrieval operation binding the contract event 0x120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a. // -// Solidity: event GuardAdded(address guard) -func (_FastBridge *FastBridgeFilterer) FilterGuardAdded(opts *bind.FilterOpts) (*FastBridgeGuardAddedIterator, error) { +// Solidity: event BridgeRequested(bytes32 indexed transactionId, address indexed sender, bytes request, uint32 destChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, bool sendChainGas) +func (_FastBridge *FastBridgeFilterer) FilterBridgeRequested(opts *bind.FilterOpts, transactionId [][32]byte, sender []common.Address) (*FastBridgeBridgeRequestedIterator, error) { + + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "GuardAdded") + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeRequested", transactionIdRule, senderRule) if err != nil { return nil, err } - return &FastBridgeGuardAddedIterator{contract: _FastBridge.contract, event: "GuardAdded", logs: logs, sub: sub}, nil + return &FastBridgeBridgeRequestedIterator{contract: _FastBridge.contract, event: "BridgeRequested", logs: logs, sub: sub}, nil } -// WatchGuardAdded is a free log subscription operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// WatchBridgeRequested is a free log subscription operation binding the contract event 0x120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a. // -// Solidity: event GuardAdded(address guard) -func (_FastBridge *FastBridgeFilterer) WatchGuardAdded(opts *bind.WatchOpts, sink chan<- *FastBridgeGuardAdded) (event.Subscription, error) { +// Solidity: event BridgeRequested(bytes32 indexed transactionId, address indexed sender, bytes request, uint32 destChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, bool sendChainGas) +func (_FastBridge *FastBridgeFilterer) WatchBridgeRequested(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeRequested, transactionId [][32]byte, sender []common.Address) (event.Subscription, error) { + + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "GuardAdded") + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeRequested", transactionIdRule, senderRule) if err != nil { return nil, err } @@ -6952,8 +6342,8 @@ func (_FastBridge *FastBridgeFilterer) WatchGuardAdded(opts *bind.WatchOpts, sin select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeGuardAdded) - if err := _FastBridge.contract.UnpackLog(event, "GuardAdded", log); err != nil { + event := new(FastBridgeBridgeRequested) + if err := _FastBridge.contract.UnpackLog(event, "BridgeRequested", log); err != nil { return err } event.Raw = log @@ -6974,21 +6364,21 @@ func (_FastBridge *FastBridgeFilterer) WatchGuardAdded(opts *bind.WatchOpts, sin }), nil } -// ParseGuardAdded is a log parse operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// ParseBridgeRequested is a log parse operation binding the contract event 0x120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a. // -// Solidity: event GuardAdded(address guard) -func (_FastBridge *FastBridgeFilterer) ParseGuardAdded(log types.Log) (*FastBridgeGuardAdded, error) { - event := new(FastBridgeGuardAdded) - if err := _FastBridge.contract.UnpackLog(event, "GuardAdded", log); err != nil { +// Solidity: event BridgeRequested(bytes32 indexed transactionId, address indexed sender, bytes request, uint32 destChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, bool sendChainGas) +func (_FastBridge *FastBridgeFilterer) ParseBridgeRequested(log types.Log) (*FastBridgeBridgeRequested, error) { + event := new(FastBridgeBridgeRequested) + if err := _FastBridge.contract.UnpackLog(event, "BridgeRequested", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeGuardRemovedIterator is returned from FilterGuardRemoved and is used to iterate over the raw logs and unpacked data for GuardRemoved events raised by the FastBridge contract. -type FastBridgeGuardRemovedIterator struct { - Event *FastBridgeGuardRemoved // Event containing the contract specifics and raw log +// FastBridgeChainGasAmountUpdatedIterator is returned from FilterChainGasAmountUpdated and is used to iterate over the raw logs and unpacked data for ChainGasAmountUpdated events raised by the FastBridge contract. +type FastBridgeChainGasAmountUpdatedIterator struct { + Event *FastBridgeChainGasAmountUpdated // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -7002,7 +6392,7 @@ type FastBridgeGuardRemovedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeGuardRemovedIterator) Next() bool { +func (it *FastBridgeChainGasAmountUpdatedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -7011,7 +6401,7 @@ func (it *FastBridgeGuardRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeGuardRemoved) + it.Event = new(FastBridgeChainGasAmountUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -7026,7 +6416,7 @@ func (it *FastBridgeGuardRemovedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeGuardRemoved) + it.Event = new(FastBridgeChainGasAmountUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -7042,41 +6432,42 @@ func (it *FastBridgeGuardRemovedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeGuardRemovedIterator) Error() error { +func (it *FastBridgeChainGasAmountUpdatedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeGuardRemovedIterator) Close() error { +func (it *FastBridgeChainGasAmountUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeGuardRemoved represents a GuardRemoved event raised by the FastBridge contract. -type FastBridgeGuardRemoved struct { - Guard common.Address - Raw types.Log // Blockchain specific contextual infos +// FastBridgeChainGasAmountUpdated represents a ChainGasAmountUpdated event raised by the FastBridge contract. +type FastBridgeChainGasAmountUpdated struct { + OldChainGasAmount *big.Int + NewChainGasAmount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterGuardRemoved is a free log retrieval operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// FilterChainGasAmountUpdated is a free log retrieval operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event GuardRemoved(address guard) -func (_FastBridge *FastBridgeFilterer) FilterGuardRemoved(opts *bind.FilterOpts) (*FastBridgeGuardRemovedIterator, error) { +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_FastBridge *FastBridgeFilterer) FilterChainGasAmountUpdated(opts *bind.FilterOpts) (*FastBridgeChainGasAmountUpdatedIterator, error) { - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "GuardRemoved") + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "ChainGasAmountUpdated") if err != nil { return nil, err } - return &FastBridgeGuardRemovedIterator{contract: _FastBridge.contract, event: "GuardRemoved", logs: logs, sub: sub}, nil + return &FastBridgeChainGasAmountUpdatedIterator{contract: _FastBridge.contract, event: "ChainGasAmountUpdated", logs: logs, sub: sub}, nil } -// WatchGuardRemoved is a free log subscription operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// WatchChainGasAmountUpdated is a free log subscription operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event GuardRemoved(address guard) -func (_FastBridge *FastBridgeFilterer) WatchGuardRemoved(opts *bind.WatchOpts, sink chan<- *FastBridgeGuardRemoved) (event.Subscription, error) { +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_FastBridge *FastBridgeFilterer) WatchChainGasAmountUpdated(opts *bind.WatchOpts, sink chan<- *FastBridgeChainGasAmountUpdated) (event.Subscription, error) { - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "GuardRemoved") + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "ChainGasAmountUpdated") if err != nil { return nil, err } @@ -7086,8 +6477,8 @@ func (_FastBridge *FastBridgeFilterer) WatchGuardRemoved(opts *bind.WatchOpts, s select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeGuardRemoved) - if err := _FastBridge.contract.UnpackLog(event, "GuardRemoved", log); err != nil { + event := new(FastBridgeChainGasAmountUpdated) + if err := _FastBridge.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { return err } event.Raw = log @@ -7108,21 +6499,21 @@ func (_FastBridge *FastBridgeFilterer) WatchGuardRemoved(opts *bind.WatchOpts, s }), nil } -// ParseGuardRemoved is a log parse operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// ParseChainGasAmountUpdated is a log parse operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event GuardRemoved(address guard) -func (_FastBridge *FastBridgeFilterer) ParseGuardRemoved(log types.Log) (*FastBridgeGuardRemoved, error) { - event := new(FastBridgeGuardRemoved) - if err := _FastBridge.contract.UnpackLog(event, "GuardRemoved", log); err != nil { +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_FastBridge *FastBridgeFilterer) ParseChainGasAmountUpdated(log types.Log) (*FastBridgeChainGasAmountUpdated, error) { + event := new(FastBridgeChainGasAmountUpdated) + if err := _FastBridge.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeRelayerAddedIterator is returned from FilterRelayerAdded and is used to iterate over the raw logs and unpacked data for RelayerAdded events raised by the FastBridge contract. -type FastBridgeRelayerAddedIterator struct { - Event *FastBridgeRelayerAdded // Event containing the contract specifics and raw log +// FastBridgeFeeRateUpdatedIterator is returned from FilterFeeRateUpdated and is used to iterate over the raw logs and unpacked data for FeeRateUpdated events raised by the FastBridge contract. +type FastBridgeFeeRateUpdatedIterator struct { + Event *FastBridgeFeeRateUpdated // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -7136,7 +6527,7 @@ type FastBridgeRelayerAddedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeRelayerAddedIterator) Next() bool { +func (it *FastBridgeFeeRateUpdatedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -7145,7 +6536,7 @@ func (it *FastBridgeRelayerAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeRelayerAdded) + it.Event = new(FastBridgeFeeRateUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -7160,7 +6551,7 @@ func (it *FastBridgeRelayerAddedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeRelayerAdded) + it.Event = new(FastBridgeFeeRateUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -7176,41 +6567,42 @@ func (it *FastBridgeRelayerAddedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeRelayerAddedIterator) Error() error { +func (it *FastBridgeFeeRateUpdatedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeRelayerAddedIterator) Close() error { +func (it *FastBridgeFeeRateUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeRelayerAdded represents a RelayerAdded event raised by the FastBridge contract. -type FastBridgeRelayerAdded struct { - Relayer common.Address - Raw types.Log // Blockchain specific contextual infos +// FastBridgeFeeRateUpdated represents a FeeRateUpdated event raised by the FastBridge contract. +type FastBridgeFeeRateUpdated struct { + OldFeeRate *big.Int + NewFeeRate *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterRelayerAdded is a free log retrieval operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// FilterFeeRateUpdated is a free log retrieval operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. // -// Solidity: event RelayerAdded(address relayer) -func (_FastBridge *FastBridgeFilterer) FilterRelayerAdded(opts *bind.FilterOpts) (*FastBridgeRelayerAddedIterator, error) { +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_FastBridge *FastBridgeFilterer) FilterFeeRateUpdated(opts *bind.FilterOpts) (*FastBridgeFeeRateUpdatedIterator, error) { - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "RelayerAdded") + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "FeeRateUpdated") if err != nil { return nil, err } - return &FastBridgeRelayerAddedIterator{contract: _FastBridge.contract, event: "RelayerAdded", logs: logs, sub: sub}, nil + return &FastBridgeFeeRateUpdatedIterator{contract: _FastBridge.contract, event: "FeeRateUpdated", logs: logs, sub: sub}, nil } -// WatchRelayerAdded is a free log subscription operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// WatchFeeRateUpdated is a free log subscription operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. // -// Solidity: event RelayerAdded(address relayer) -func (_FastBridge *FastBridgeFilterer) WatchRelayerAdded(opts *bind.WatchOpts, sink chan<- *FastBridgeRelayerAdded) (event.Subscription, error) { +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_FastBridge *FastBridgeFilterer) WatchFeeRateUpdated(opts *bind.WatchOpts, sink chan<- *FastBridgeFeeRateUpdated) (event.Subscription, error) { - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "RelayerAdded") + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "FeeRateUpdated") if err != nil { return nil, err } @@ -7220,8 +6612,8 @@ func (_FastBridge *FastBridgeFilterer) WatchRelayerAdded(opts *bind.WatchOpts, s select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeRelayerAdded) - if err := _FastBridge.contract.UnpackLog(event, "RelayerAdded", log); err != nil { + event := new(FastBridgeFeeRateUpdated) + if err := _FastBridge.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { return err } event.Raw = log @@ -7242,21 +6634,21 @@ func (_FastBridge *FastBridgeFilterer) WatchRelayerAdded(opts *bind.WatchOpts, s }), nil } -// ParseRelayerAdded is a log parse operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// ParseFeeRateUpdated is a log parse operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. // -// Solidity: event RelayerAdded(address relayer) -func (_FastBridge *FastBridgeFilterer) ParseRelayerAdded(log types.Log) (*FastBridgeRelayerAdded, error) { - event := new(FastBridgeRelayerAdded) - if err := _FastBridge.contract.UnpackLog(event, "RelayerAdded", log); err != nil { +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_FastBridge *FastBridgeFilterer) ParseFeeRateUpdated(log types.Log) (*FastBridgeFeeRateUpdated, error) { + event := new(FastBridgeFeeRateUpdated) + if err := _FastBridge.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeRelayerRemovedIterator is returned from FilterRelayerRemoved and is used to iterate over the raw logs and unpacked data for RelayerRemoved events raised by the FastBridge contract. -type FastBridgeRelayerRemovedIterator struct { - Event *FastBridgeRelayerRemoved // Event containing the contract specifics and raw log +// FastBridgeFeesSweptIterator is returned from FilterFeesSwept and is used to iterate over the raw logs and unpacked data for FeesSwept events raised by the FastBridge contract. +type FastBridgeFeesSweptIterator struct { + Event *FastBridgeFeesSwept // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -7270,7 +6662,7 @@ type FastBridgeRelayerRemovedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeRelayerRemovedIterator) Next() bool { +func (it *FastBridgeFeesSweptIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -7279,7 +6671,7 @@ func (it *FastBridgeRelayerRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeRelayerRemoved) + it.Event = new(FastBridgeFeesSwept) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -7294,7 +6686,7 @@ func (it *FastBridgeRelayerRemovedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeRelayerRemoved) + it.Event = new(FastBridgeFeesSwept) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -7310,41 +6702,43 @@ func (it *FastBridgeRelayerRemovedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeRelayerRemovedIterator) Error() error { +func (it *FastBridgeFeesSweptIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeRelayerRemovedIterator) Close() error { +func (it *FastBridgeFeesSweptIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeRelayerRemoved represents a RelayerRemoved event raised by the FastBridge contract. -type FastBridgeRelayerRemoved struct { - Relayer common.Address - Raw types.Log // Blockchain specific contextual infos +// FastBridgeFeesSwept represents a FeesSwept event raised by the FastBridge contract. +type FastBridgeFeesSwept struct { + Token common.Address + Recipient common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterRelayerRemoved is a free log retrieval operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// FilterFeesSwept is a free log retrieval operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. // -// Solidity: event RelayerRemoved(address relayer) -func (_FastBridge *FastBridgeFilterer) FilterRelayerRemoved(opts *bind.FilterOpts) (*FastBridgeRelayerRemovedIterator, error) { +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_FastBridge *FastBridgeFilterer) FilterFeesSwept(opts *bind.FilterOpts) (*FastBridgeFeesSweptIterator, error) { - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "RelayerRemoved") + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "FeesSwept") if err != nil { return nil, err } - return &FastBridgeRelayerRemovedIterator{contract: _FastBridge.contract, event: "RelayerRemoved", logs: logs, sub: sub}, nil + return &FastBridgeFeesSweptIterator{contract: _FastBridge.contract, event: "FeesSwept", logs: logs, sub: sub}, nil } -// WatchRelayerRemoved is a free log subscription operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// WatchFeesSwept is a free log subscription operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. // -// Solidity: event RelayerRemoved(address relayer) -func (_FastBridge *FastBridgeFilterer) WatchRelayerRemoved(opts *bind.WatchOpts, sink chan<- *FastBridgeRelayerRemoved) (event.Subscription, error) { +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_FastBridge *FastBridgeFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink chan<- *FastBridgeFeesSwept) (event.Subscription, error) { - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "RelayerRemoved") + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "FeesSwept") if err != nil { return nil, err } @@ -7354,8 +6748,8 @@ func (_FastBridge *FastBridgeFilterer) WatchRelayerRemoved(opts *bind.WatchOpts, select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeRelayerRemoved) - if err := _FastBridge.contract.UnpackLog(event, "RelayerRemoved", log); err != nil { + event := new(FastBridgeFeesSwept) + if err := _FastBridge.contract.UnpackLog(event, "FeesSwept", log); err != nil { return err } event.Raw = log @@ -7376,12 +6770,12 @@ func (_FastBridge *FastBridgeFilterer) WatchRelayerRemoved(opts *bind.WatchOpts, }), nil } -// ParseRelayerRemoved is a log parse operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// ParseFeesSwept is a log parse operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. // -// Solidity: event RelayerRemoved(address relayer) -func (_FastBridge *FastBridgeFilterer) ParseRelayerRemoved(log types.Log) (*FastBridgeRelayerRemoved, error) { - event := new(FastBridgeRelayerRemoved) - if err := _FastBridge.contract.UnpackLog(event, "RelayerRemoved", log); err != nil { +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_FastBridge *FastBridgeFilterer) ParseFeesSwept(log types.Log) (*FastBridgeFeesSwept, error) { + event := new(FastBridgeFeesSwept) + if err := _FastBridge.contract.UnpackLog(event, "FeesSwept", log); err != nil { return nil, err } event.Raw = log @@ -8647,128 +8041,126 @@ func (_IAccessControl *IAccessControlFilterer) ParseRoleRevoked(log types.Log) ( return event, nil } -// IAdminMetaData contains all meta data concerning the IAdmin contract. -var IAdminMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerRemoved\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"addGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"addGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"addRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"removeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"removeGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"removeRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +// IAccessControlEnumerableMetaData contains all meta data concerning the IAccessControlEnumerable contract. +var IAccessControlEnumerableMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", Sigs: map[string]string{ - "3c4a25d0": "addGovernor(address)", - "6913a63c": "addGuard(address)", - "dd39f00d": "addRelayer(address)", - "eecdac88": "removeGovernor(address)", - "b6235016": "removeGuard(address)", - "60f0a5ac": "removeRelayer(address)", - "b250fe6b": "setChainGasAmount(uint256)", - "b13aa2d6": "setProtocolFeeRate(uint256)", - "06f333f2": "sweepProtocolFees(address,address)", + "248a9ca3": "getRoleAdmin(bytes32)", + "9010d07c": "getRoleMember(bytes32,uint256)", + "ca15c873": "getRoleMemberCount(bytes32)", + "2f2ff15d": "grantRole(bytes32,address)", + "91d14854": "hasRole(bytes32,address)", + "36568abe": "renounceRole(bytes32,address)", + "d547741f": "revokeRole(bytes32,address)", }, } -// IAdminABI is the input ABI used to generate the binding from. -// Deprecated: Use IAdminMetaData.ABI instead. -var IAdminABI = IAdminMetaData.ABI +// IAccessControlEnumerableABI is the input ABI used to generate the binding from. +// Deprecated: Use IAccessControlEnumerableMetaData.ABI instead. +var IAccessControlEnumerableABI = IAccessControlEnumerableMetaData.ABI -// Deprecated: Use IAdminMetaData.Sigs instead. -// IAdminFuncSigs maps the 4-byte function signature to its string representation. -var IAdminFuncSigs = IAdminMetaData.Sigs +// Deprecated: Use IAccessControlEnumerableMetaData.Sigs instead. +// IAccessControlEnumerableFuncSigs maps the 4-byte function signature to its string representation. +var IAccessControlEnumerableFuncSigs = IAccessControlEnumerableMetaData.Sigs -// IAdmin is an auto generated Go binding around an Ethereum contract. -type IAdmin struct { - IAdminCaller // Read-only binding to the contract - IAdminTransactor // Write-only binding to the contract - IAdminFilterer // Log filterer for contract events +// IAccessControlEnumerable is an auto generated Go binding around an Ethereum contract. +type IAccessControlEnumerable struct { + IAccessControlEnumerableCaller // Read-only binding to the contract + IAccessControlEnumerableTransactor // Write-only binding to the contract + IAccessControlEnumerableFilterer // Log filterer for contract events } -// IAdminCaller is an auto generated read-only Go binding around an Ethereum contract. -type IAdminCaller struct { +// IAccessControlEnumerableCaller is an auto generated read-only Go binding around an Ethereum contract. +type IAccessControlEnumerableCaller struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// IAdminTransactor is an auto generated write-only Go binding around an Ethereum contract. -type IAdminTransactor struct { +// IAccessControlEnumerableTransactor is an auto generated write-only Go binding around an Ethereum contract. +type IAccessControlEnumerableTransactor struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// IAdminFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type IAdminFilterer struct { +// IAccessControlEnumerableFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IAccessControlEnumerableFilterer struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// IAdminSession is an auto generated Go binding around an Ethereum contract, +// IAccessControlEnumerableSession is an auto generated Go binding around an Ethereum contract, // with pre-set call and transact options. -type IAdminSession struct { - Contract *IAdmin // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +type IAccessControlEnumerableSession struct { + Contract *IAccessControlEnumerable // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// IAdminCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// IAccessControlEnumerableCallerSession is an auto generated read-only Go binding around an Ethereum contract, // with pre-set call options. -type IAdminCallerSession struct { - Contract *IAdminCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session +type IAccessControlEnumerableCallerSession struct { + Contract *IAccessControlEnumerableCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session } -// IAdminTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// IAccessControlEnumerableTransactorSession is an auto generated write-only Go binding around an Ethereum contract, // with pre-set transact options. -type IAdminTransactorSession struct { - Contract *IAdminTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +type IAccessControlEnumerableTransactorSession struct { + Contract *IAccessControlEnumerableTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// IAdminRaw is an auto generated low-level Go binding around an Ethereum contract. -type IAdminRaw struct { - Contract *IAdmin // Generic contract binding to access the raw methods on +// IAccessControlEnumerableRaw is an auto generated low-level Go binding around an Ethereum contract. +type IAccessControlEnumerableRaw struct { + Contract *IAccessControlEnumerable // Generic contract binding to access the raw methods on } -// IAdminCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type IAdminCallerRaw struct { - Contract *IAdminCaller // Generic read-only contract binding to access the raw methods on +// IAccessControlEnumerableCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IAccessControlEnumerableCallerRaw struct { + Contract *IAccessControlEnumerableCaller // Generic read-only contract binding to access the raw methods on } -// IAdminTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type IAdminTransactorRaw struct { - Contract *IAdminTransactor // Generic write-only contract binding to access the raw methods on +// IAccessControlEnumerableTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IAccessControlEnumerableTransactorRaw struct { + Contract *IAccessControlEnumerableTransactor // Generic write-only contract binding to access the raw methods on } -// NewIAdmin creates a new instance of IAdmin, bound to a specific deployed contract. -func NewIAdmin(address common.Address, backend bind.ContractBackend) (*IAdmin, error) { - contract, err := bindIAdmin(address, backend, backend, backend) +// NewIAccessControlEnumerable creates a new instance of IAccessControlEnumerable, bound to a specific deployed contract. +func NewIAccessControlEnumerable(address common.Address, backend bind.ContractBackend) (*IAccessControlEnumerable, error) { + contract, err := bindIAccessControlEnumerable(address, backend, backend, backend) if err != nil { return nil, err } - return &IAdmin{IAdminCaller: IAdminCaller{contract: contract}, IAdminTransactor: IAdminTransactor{contract: contract}, IAdminFilterer: IAdminFilterer{contract: contract}}, nil + return &IAccessControlEnumerable{IAccessControlEnumerableCaller: IAccessControlEnumerableCaller{contract: contract}, IAccessControlEnumerableTransactor: IAccessControlEnumerableTransactor{contract: contract}, IAccessControlEnumerableFilterer: IAccessControlEnumerableFilterer{contract: contract}}, nil } -// NewIAdminCaller creates a new read-only instance of IAdmin, bound to a specific deployed contract. -func NewIAdminCaller(address common.Address, caller bind.ContractCaller) (*IAdminCaller, error) { - contract, err := bindIAdmin(address, caller, nil, nil) +// NewIAccessControlEnumerableCaller creates a new read-only instance of IAccessControlEnumerable, bound to a specific deployed contract. +func NewIAccessControlEnumerableCaller(address common.Address, caller bind.ContractCaller) (*IAccessControlEnumerableCaller, error) { + contract, err := bindIAccessControlEnumerable(address, caller, nil, nil) if err != nil { return nil, err } - return &IAdminCaller{contract: contract}, nil + return &IAccessControlEnumerableCaller{contract: contract}, nil } -// NewIAdminTransactor creates a new write-only instance of IAdmin, bound to a specific deployed contract. -func NewIAdminTransactor(address common.Address, transactor bind.ContractTransactor) (*IAdminTransactor, error) { - contract, err := bindIAdmin(address, nil, transactor, nil) +// NewIAccessControlEnumerableTransactor creates a new write-only instance of IAccessControlEnumerable, bound to a specific deployed contract. +func NewIAccessControlEnumerableTransactor(address common.Address, transactor bind.ContractTransactor) (*IAccessControlEnumerableTransactor, error) { + contract, err := bindIAccessControlEnumerable(address, nil, transactor, nil) if err != nil { return nil, err } - return &IAdminTransactor{contract: contract}, nil + return &IAccessControlEnumerableTransactor{contract: contract}, nil } -// NewIAdminFilterer creates a new log filterer instance of IAdmin, bound to a specific deployed contract. -func NewIAdminFilterer(address common.Address, filterer bind.ContractFilterer) (*IAdminFilterer, error) { - contract, err := bindIAdmin(address, nil, nil, filterer) +// NewIAccessControlEnumerableFilterer creates a new log filterer instance of IAccessControlEnumerable, bound to a specific deployed contract. +func NewIAccessControlEnumerableFilterer(address common.Address, filterer bind.ContractFilterer) (*IAccessControlEnumerableFilterer, error) { + contract, err := bindIAccessControlEnumerable(address, nil, nil, filterer) if err != nil { return nil, err } - return &IAdminFilterer{contract: contract}, nil + return &IAccessControlEnumerableFilterer{contract: contract}, nil } -// bindIAdmin binds a generic wrapper to an already deployed contract. -func bindIAdmin(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := IAdminMetaData.GetAbi() +// bindIAccessControlEnumerable binds a generic wrapper to an already deployed contract. +func bindIAccessControlEnumerable(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := IAccessControlEnumerableMetaData.GetAbi() if err != nil { return nil, err } @@ -8779,502 +8171,230 @@ func bindIAdmin(address common.Address, caller bind.ContractCaller, transactor b // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. -func (_IAdmin *IAdminRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _IAdmin.Contract.IAdminCaller.contract.Call(opts, result, method, params...) +func (_IAccessControlEnumerable *IAccessControlEnumerableRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IAccessControlEnumerable.Contract.IAccessControlEnumerableCaller.contract.Call(opts, result, method, params...) } // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. -func (_IAdmin *IAdminRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _IAdmin.Contract.IAdminTransactor.contract.Transfer(opts) +func (_IAccessControlEnumerable *IAccessControlEnumerableRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.IAccessControlEnumerableTransactor.contract.Transfer(opts) } // Transact invokes the (paid) contract method with params as input values. -func (_IAdmin *IAdminRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _IAdmin.Contract.IAdminTransactor.contract.Transact(opts, method, params...) +func (_IAccessControlEnumerable *IAccessControlEnumerableRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.IAccessControlEnumerableTransactor.contract.Transact(opts, method, params...) } // Call invokes the (constant) contract method with params as input values and // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. -func (_IAdmin *IAdminCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _IAdmin.Contract.contract.Call(opts, result, method, params...) +func (_IAccessControlEnumerable *IAccessControlEnumerableCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IAccessControlEnumerable.Contract.contract.Call(opts, result, method, params...) } // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. -func (_IAdmin *IAdminTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _IAdmin.Contract.contract.Transfer(opts) +func (_IAccessControlEnumerable *IAccessControlEnumerableTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.contract.Transfer(opts) } // Transact invokes the (paid) contract method with params as input values. -func (_IAdmin *IAdminTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _IAdmin.Contract.contract.Transact(opts, method, params...) -} - -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. -// -// Solidity: function addGovernor(address _governor) returns() -func (_IAdmin *IAdminTransactor) AddGovernor(opts *bind.TransactOpts, _governor common.Address) (*types.Transaction, error) { - return _IAdmin.contract.Transact(opts, "addGovernor", _governor) -} - -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. -// -// Solidity: function addGovernor(address _governor) returns() -func (_IAdmin *IAdminSession) AddGovernor(_governor common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.AddGovernor(&_IAdmin.TransactOpts, _governor) -} - -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. -// -// Solidity: function addGovernor(address _governor) returns() -func (_IAdmin *IAdminTransactorSession) AddGovernor(_governor common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.AddGovernor(&_IAdmin.TransactOpts, _governor) -} - -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. -// -// Solidity: function addGuard(address _guard) returns() -func (_IAdmin *IAdminTransactor) AddGuard(opts *bind.TransactOpts, _guard common.Address) (*types.Transaction, error) { - return _IAdmin.contract.Transact(opts, "addGuard", _guard) -} - -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. -// -// Solidity: function addGuard(address _guard) returns() -func (_IAdmin *IAdminSession) AddGuard(_guard common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.AddGuard(&_IAdmin.TransactOpts, _guard) -} - -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. -// -// Solidity: function addGuard(address _guard) returns() -func (_IAdmin *IAdminTransactorSession) AddGuard(_guard common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.AddGuard(&_IAdmin.TransactOpts, _guard) -} - -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. -// -// Solidity: function addRelayer(address _relayer) returns() -func (_IAdmin *IAdminTransactor) AddRelayer(opts *bind.TransactOpts, _relayer common.Address) (*types.Transaction, error) { - return _IAdmin.contract.Transact(opts, "addRelayer", _relayer) -} - -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. -// -// Solidity: function addRelayer(address _relayer) returns() -func (_IAdmin *IAdminSession) AddRelayer(_relayer common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.AddRelayer(&_IAdmin.TransactOpts, _relayer) -} - -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. -// -// Solidity: function addRelayer(address _relayer) returns() -func (_IAdmin *IAdminTransactorSession) AddRelayer(_relayer common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.AddRelayer(&_IAdmin.TransactOpts, _relayer) -} - -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. -// -// Solidity: function removeGovernor(address _governor) returns() -func (_IAdmin *IAdminTransactor) RemoveGovernor(opts *bind.TransactOpts, _governor common.Address) (*types.Transaction, error) { - return _IAdmin.contract.Transact(opts, "removeGovernor", _governor) -} - -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. -// -// Solidity: function removeGovernor(address _governor) returns() -func (_IAdmin *IAdminSession) RemoveGovernor(_governor common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.RemoveGovernor(&_IAdmin.TransactOpts, _governor) -} - -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. -// -// Solidity: function removeGovernor(address _governor) returns() -func (_IAdmin *IAdminTransactorSession) RemoveGovernor(_governor common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.RemoveGovernor(&_IAdmin.TransactOpts, _governor) -} - -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. -// -// Solidity: function removeGuard(address _guard) returns() -func (_IAdmin *IAdminTransactor) RemoveGuard(opts *bind.TransactOpts, _guard common.Address) (*types.Transaction, error) { - return _IAdmin.contract.Transact(opts, "removeGuard", _guard) -} - -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. -// -// Solidity: function removeGuard(address _guard) returns() -func (_IAdmin *IAdminSession) RemoveGuard(_guard common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.RemoveGuard(&_IAdmin.TransactOpts, _guard) -} - -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. -// -// Solidity: function removeGuard(address _guard) returns() -func (_IAdmin *IAdminTransactorSession) RemoveGuard(_guard common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.RemoveGuard(&_IAdmin.TransactOpts, _guard) -} - -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. -// -// Solidity: function removeRelayer(address _relayer) returns() -func (_IAdmin *IAdminTransactor) RemoveRelayer(opts *bind.TransactOpts, _relayer common.Address) (*types.Transaction, error) { - return _IAdmin.contract.Transact(opts, "removeRelayer", _relayer) -} - -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. -// -// Solidity: function removeRelayer(address _relayer) returns() -func (_IAdmin *IAdminSession) RemoveRelayer(_relayer common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.RemoveRelayer(&_IAdmin.TransactOpts, _relayer) -} - -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. -// -// Solidity: function removeRelayer(address _relayer) returns() -func (_IAdmin *IAdminTransactorSession) RemoveRelayer(_relayer common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.RemoveRelayer(&_IAdmin.TransactOpts, _relayer) -} - -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. -// -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_IAdmin *IAdminTransactor) SetChainGasAmount(opts *bind.TransactOpts, newChainGasAmount *big.Int) (*types.Transaction, error) { - return _IAdmin.contract.Transact(opts, "setChainGasAmount", newChainGasAmount) -} - -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. -// -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_IAdmin *IAdminSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { - return _IAdmin.Contract.SetChainGasAmount(&_IAdmin.TransactOpts, newChainGasAmount) -} - -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. -// -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_IAdmin *IAdminTransactorSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { - return _IAdmin.Contract.SetChainGasAmount(&_IAdmin.TransactOpts, newChainGasAmount) -} - -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. -// -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_IAdmin *IAdminTransactor) SetProtocolFeeRate(opts *bind.TransactOpts, newFeeRate *big.Int) (*types.Transaction, error) { - return _IAdmin.contract.Transact(opts, "setProtocolFeeRate", newFeeRate) -} - -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. -// -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_IAdmin *IAdminSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { - return _IAdmin.Contract.SetProtocolFeeRate(&_IAdmin.TransactOpts, newFeeRate) -} - -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. -// -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_IAdmin *IAdminTransactorSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { - return _IAdmin.Contract.SetProtocolFeeRate(&_IAdmin.TransactOpts, newFeeRate) -} - -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. -// -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_IAdmin *IAdminTransactor) SweepProtocolFees(opts *bind.TransactOpts, token common.Address, recipient common.Address) (*types.Transaction, error) { - return _IAdmin.contract.Transact(opts, "sweepProtocolFees", token, recipient) -} - -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. -// -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_IAdmin *IAdminSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.SweepProtocolFees(&_IAdmin.TransactOpts, token, recipient) -} - -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. -// -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_IAdmin *IAdminTransactorSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.SweepProtocolFees(&_IAdmin.TransactOpts, token, recipient) -} - -// IAdminChainGasAmountUpdatedIterator is returned from FilterChainGasAmountUpdated and is used to iterate over the raw logs and unpacked data for ChainGasAmountUpdated events raised by the IAdmin contract. -type IAdminChainGasAmountUpdatedIterator struct { - Event *IAdminChainGasAmountUpdated // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *IAdminChainGasAmountUpdatedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(IAdminChainGasAmountUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(IAdminChainGasAmountUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +func (_IAccessControlEnumerable *IAccessControlEnumerableTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.contract.Transact(opts, method, params...) +} - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_IAccessControlEnumerable *IAccessControlEnumerableCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { + var out []interface{} + err := _IAccessControlEnumerable.contract.Call(opts, &out, "getRoleAdmin", role) + + if err != nil { + return *new([32]byte), err } -} -// Error returns any retrieval or parsing error occurred during filtering. -func (it *IAdminChainGasAmountUpdatedIterator) Error() error { - return it.fail + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *IAdminChainGasAmountUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_IAccessControlEnumerable *IAccessControlEnumerableSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _IAccessControlEnumerable.Contract.GetRoleAdmin(&_IAccessControlEnumerable.CallOpts, role) } -// IAdminChainGasAmountUpdated represents a ChainGasAmountUpdated event raised by the IAdmin contract. -type IAdminChainGasAmountUpdated struct { - OldChainGasAmount *big.Int - NewChainGasAmount *big.Int - Raw types.Log // Blockchain specific contextual infos +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_IAccessControlEnumerable *IAccessControlEnumerableCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _IAccessControlEnumerable.Contract.GetRoleAdmin(&_IAccessControlEnumerable.CallOpts, role) } -// FilterChainGasAmountUpdated is a free log retrieval operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_IAdmin *IAdminFilterer) FilterChainGasAmountUpdated(opts *bind.FilterOpts) (*IAdminChainGasAmountUpdatedIterator, error) { +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_IAccessControlEnumerable *IAccessControlEnumerableCaller) GetRoleMember(opts *bind.CallOpts, role [32]byte, index *big.Int) (common.Address, error) { + var out []interface{} + err := _IAccessControlEnumerable.contract.Call(opts, &out, "getRoleMember", role, index) - logs, sub, err := _IAdmin.contract.FilterLogs(opts, "ChainGasAmountUpdated") if err != nil { - return nil, err + return *new(common.Address), err } - return &IAdminChainGasAmountUpdatedIterator{contract: _IAdmin.contract, event: "ChainGasAmountUpdated", logs: logs, sub: sub}, nil + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + } -// WatchChainGasAmountUpdated is a free log subscription operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_IAdmin *IAdminFilterer) WatchChainGasAmountUpdated(opts *bind.WatchOpts, sink chan<- *IAdminChainGasAmountUpdated) (event.Subscription, error) { +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_IAccessControlEnumerable *IAccessControlEnumerableSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _IAccessControlEnumerable.Contract.GetRoleMember(&_IAccessControlEnumerable.CallOpts, role, index) +} + +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. +// +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_IAccessControlEnumerable *IAccessControlEnumerableCallerSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _IAccessControlEnumerable.Contract.GetRoleMember(&_IAccessControlEnumerable.CallOpts, role, index) +} + +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. +// +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_IAccessControlEnumerable *IAccessControlEnumerableCaller) GetRoleMemberCount(opts *bind.CallOpts, role [32]byte) (*big.Int, error) { + var out []interface{} + err := _IAccessControlEnumerable.contract.Call(opts, &out, "getRoleMemberCount", role) - logs, sub, err := _IAdmin.contract.WatchLogs(opts, "ChainGasAmountUpdated") if err != nil { - return nil, err + return *new(*big.Int), err } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(IAdminChainGasAmountUpdated) - if err := _IAdmin.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { - return err - } - event.Raw = log - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// ParseChainGasAmountUpdated is a log parse operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_IAdmin *IAdminFilterer) ParseChainGasAmountUpdated(log types.Log) (*IAdminChainGasAmountUpdated, error) { - event := new(IAdminChainGasAmountUpdated) - if err := _IAdmin.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_IAccessControlEnumerable *IAccessControlEnumerableSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _IAccessControlEnumerable.Contract.GetRoleMemberCount(&_IAccessControlEnumerable.CallOpts, role) } -// IAdminFeeRateUpdatedIterator is returned from FilterFeeRateUpdated and is used to iterate over the raw logs and unpacked data for FeeRateUpdated events raised by the IAdmin contract. -type IAdminFeeRateUpdatedIterator struct { - Event *IAdminFeeRateUpdated // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. +// +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_IAccessControlEnumerable *IAccessControlEnumerableCallerSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _IAccessControlEnumerable.Contract.GetRoleMemberCount(&_IAccessControlEnumerable.CallOpts, role) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *IAdminFeeRateUpdatedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(IAdminFeeRateUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_IAccessControlEnumerable *IAccessControlEnumerableCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { + var out []interface{} + err := _IAccessControlEnumerable.contract.Call(opts, &out, "hasRole", role, account) - default: - return false - } + if err != nil { + return *new(bool), err } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(IAdminFeeRateUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + } -// Error returns any retrieval or parsing error occurred during filtering. -func (it *IAdminFeeRateUpdatedIterator) Error() error { - return it.fail +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_IAccessControlEnumerable *IAccessControlEnumerableSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _IAccessControlEnumerable.Contract.HasRole(&_IAccessControlEnumerable.CallOpts, role, account) } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *IAdminFeeRateUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_IAccessControlEnumerable *IAccessControlEnumerableCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _IAccessControlEnumerable.Contract.HasRole(&_IAccessControlEnumerable.CallOpts, role, account) } -// IAdminFeeRateUpdated represents a FeeRateUpdated event raised by the IAdmin contract. -type IAdminFeeRateUpdated struct { - OldFeeRate *big.Int - NewFeeRate *big.Int - Raw types.Log // Blockchain specific contextual infos +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_IAccessControlEnumerable *IAccessControlEnumerableTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _IAccessControlEnumerable.contract.Transact(opts, "grantRole", role, account) } -// FilterFeeRateUpdated is a free log retrieval operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. // -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_IAdmin *IAdminFilterer) FilterFeeRateUpdated(opts *bind.FilterOpts) (*IAdminFeeRateUpdatedIterator, error) { +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_IAccessControlEnumerable *IAccessControlEnumerableSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.GrantRole(&_IAccessControlEnumerable.TransactOpts, role, account) +} - logs, sub, err := _IAdmin.contract.FilterLogs(opts, "FeeRateUpdated") - if err != nil { - return nil, err - } - return &IAdminFeeRateUpdatedIterator{contract: _IAdmin.contract, event: "FeeRateUpdated", logs: logs, sub: sub}, nil +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_IAccessControlEnumerable *IAccessControlEnumerableTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.GrantRole(&_IAccessControlEnumerable.TransactOpts, role, account) } -// WatchFeeRateUpdated is a free log subscription operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. // -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_IAdmin *IAdminFilterer) WatchFeeRateUpdated(opts *bind.WatchOpts, sink chan<- *IAdminFeeRateUpdated) (event.Subscription, error) { +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_IAccessControlEnumerable *IAccessControlEnumerableTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _IAccessControlEnumerable.contract.Transact(opts, "renounceRole", role, callerConfirmation) +} - logs, sub, err := _IAdmin.contract.WatchLogs(opts, "FeeRateUpdated") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(IAdminFeeRateUpdated) - if err := _IAdmin.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { - return err - } - event.Raw = log +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_IAccessControlEnumerable *IAccessControlEnumerableSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.RenounceRole(&_IAccessControlEnumerable.TransactOpts, role, callerConfirmation) +} - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_IAccessControlEnumerable *IAccessControlEnumerableTransactorSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.RenounceRole(&_IAccessControlEnumerable.TransactOpts, role, callerConfirmation) } -// ParseFeeRateUpdated is a log parse operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. // -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_IAdmin *IAdminFilterer) ParseFeeRateUpdated(log types.Log) (*IAdminFeeRateUpdated, error) { - event := new(IAdminFeeRateUpdated) - if err := _IAdmin.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_IAccessControlEnumerable *IAccessControlEnumerableTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _IAccessControlEnumerable.contract.Transact(opts, "revokeRole", role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_IAccessControlEnumerable *IAccessControlEnumerableSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.RevokeRole(&_IAccessControlEnumerable.TransactOpts, role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_IAccessControlEnumerable *IAccessControlEnumerableTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.RevokeRole(&_IAccessControlEnumerable.TransactOpts, role, account) } -// IAdminFeesSweptIterator is returned from FilterFeesSwept and is used to iterate over the raw logs and unpacked data for FeesSwept events raised by the IAdmin contract. -type IAdminFeesSweptIterator struct { - Event *IAdminFeesSwept // Event containing the contract specifics and raw log +// IAccessControlEnumerableRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the IAccessControlEnumerable contract. +type IAccessControlEnumerableRoleAdminChangedIterator struct { + Event *IAccessControlEnumerableRoleAdminChanged // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -9288,7 +8408,7 @@ type IAdminFeesSweptIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *IAdminFeesSweptIterator) Next() bool { +func (it *IAccessControlEnumerableRoleAdminChangedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -9297,7 +8417,7 @@ func (it *IAdminFeesSweptIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(IAdminFeesSwept) + it.Event = new(IAccessControlEnumerableRoleAdminChanged) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -9312,7 +8432,7 @@ func (it *IAdminFeesSweptIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(IAdminFeesSwept) + it.Event = new(IAccessControlEnumerableRoleAdminChanged) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -9328,43 +8448,69 @@ func (it *IAdminFeesSweptIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *IAdminFeesSweptIterator) Error() error { +func (it *IAccessControlEnumerableRoleAdminChangedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *IAdminFeesSweptIterator) Close() error { +func (it *IAccessControlEnumerableRoleAdminChangedIterator) Close() error { it.sub.Unsubscribe() return nil } -// IAdminFeesSwept represents a FeesSwept event raised by the IAdmin contract. -type IAdminFeesSwept struct { - Token common.Address - Recipient common.Address - Amount *big.Int - Raw types.Log // Blockchain specific contextual infos +// IAccessControlEnumerableRoleAdminChanged represents a RoleAdminChanged event raised by the IAccessControlEnumerable contract. +type IAccessControlEnumerableRoleAdminChanged struct { + Role [32]byte + PreviousAdminRole [32]byte + NewAdminRole [32]byte + Raw types.Log // Blockchain specific contextual infos } -// FilterFeesSwept is a free log retrieval operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. // -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_IAdmin *IAdminFilterer) FilterFeesSwept(opts *bind.FilterOpts) (*IAdminFeesSweptIterator, error) { +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_IAccessControlEnumerable *IAccessControlEnumerableFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*IAccessControlEnumerableRoleAdminChangedIterator, error) { - logs, sub, err := _IAdmin.contract.FilterLogs(opts, "FeesSwept") + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + } + + logs, sub, err := _IAccessControlEnumerable.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { return nil, err } - return &IAdminFeesSweptIterator{contract: _IAdmin.contract, event: "FeesSwept", logs: logs, sub: sub}, nil + return &IAccessControlEnumerableRoleAdminChangedIterator{contract: _IAccessControlEnumerable.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil } -// WatchFeesSwept is a free log subscription operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. // -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_IAdmin *IAdminFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink chan<- *IAdminFeesSwept) (event.Subscription, error) { +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_IAccessControlEnumerable *IAccessControlEnumerableFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *IAccessControlEnumerableRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { - logs, sub, err := _IAdmin.contract.WatchLogs(opts, "FeesSwept") + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + } + + logs, sub, err := _IAccessControlEnumerable.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { return nil, err } @@ -9374,8 +8520,8 @@ func (_IAdmin *IAdminFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink chan<- select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(IAdminFeesSwept) - if err := _IAdmin.contract.UnpackLog(event, "FeesSwept", log); err != nil { + event := new(IAccessControlEnumerableRoleAdminChanged) + if err := _IAccessControlEnumerable.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { return err } event.Raw = log @@ -9396,21 +8542,21 @@ func (_IAdmin *IAdminFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink chan<- }), nil } -// ParseFeesSwept is a log parse operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. // -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_IAdmin *IAdminFilterer) ParseFeesSwept(log types.Log) (*IAdminFeesSwept, error) { - event := new(IAdminFeesSwept) - if err := _IAdmin.contract.UnpackLog(event, "FeesSwept", log); err != nil { +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_IAccessControlEnumerable *IAccessControlEnumerableFilterer) ParseRoleAdminChanged(log types.Log) (*IAccessControlEnumerableRoleAdminChanged, error) { + event := new(IAccessControlEnumerableRoleAdminChanged) + if err := _IAccessControlEnumerable.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { return nil, err } event.Raw = log return event, nil } -// IAdminGovernorAddedIterator is returned from FilterGovernorAdded and is used to iterate over the raw logs and unpacked data for GovernorAdded events raised by the IAdmin contract. -type IAdminGovernorAddedIterator struct { - Event *IAdminGovernorAdded // Event containing the contract specifics and raw log +// IAccessControlEnumerableRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the IAccessControlEnumerable contract. +type IAccessControlEnumerableRoleGrantedIterator struct { + Event *IAccessControlEnumerableRoleGranted // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -9424,7 +8570,7 @@ type IAdminGovernorAddedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *IAdminGovernorAddedIterator) Next() bool { +func (it *IAccessControlEnumerableRoleGrantedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -9433,7 +8579,7 @@ func (it *IAdminGovernorAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(IAdminGovernorAdded) + it.Event = new(IAccessControlEnumerableRoleGranted) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -9448,7 +8594,7 @@ func (it *IAdminGovernorAddedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(IAdminGovernorAdded) + it.Event = new(IAccessControlEnumerableRoleGranted) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -9464,41 +8610,69 @@ func (it *IAdminGovernorAddedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *IAdminGovernorAddedIterator) Error() error { +func (it *IAccessControlEnumerableRoleGrantedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *IAdminGovernorAddedIterator) Close() error { +func (it *IAccessControlEnumerableRoleGrantedIterator) Close() error { it.sub.Unsubscribe() return nil } -// IAdminGovernorAdded represents a GovernorAdded event raised by the IAdmin contract. -type IAdminGovernorAdded struct { - Governor common.Address - Raw types.Log // Blockchain specific contextual infos +// IAccessControlEnumerableRoleGranted represents a RoleGranted event raised by the IAccessControlEnumerable contract. +type IAccessControlEnumerableRoleGranted struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos } -// FilterGovernorAdded is a free log retrieval operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. +// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. // -// Solidity: event GovernorAdded(address governor) -func (_IAdmin *IAdminFilterer) FilterGovernorAdded(opts *bind.FilterOpts) (*IAdminGovernorAddedIterator, error) { +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_IAccessControlEnumerable *IAccessControlEnumerableFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*IAccessControlEnumerableRoleGrantedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } - logs, sub, err := _IAdmin.contract.FilterLogs(opts, "GovernorAdded") + logs, sub, err := _IAccessControlEnumerable.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) if err != nil { return nil, err } - return &IAdminGovernorAddedIterator{contract: _IAdmin.contract, event: "GovernorAdded", logs: logs, sub: sub}, nil + return &IAccessControlEnumerableRoleGrantedIterator{contract: _IAccessControlEnumerable.contract, event: "RoleGranted", logs: logs, sub: sub}, nil } -// WatchGovernorAdded is a free log subscription operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. +// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. // -// Solidity: event GovernorAdded(address governor) -func (_IAdmin *IAdminFilterer) WatchGovernorAdded(opts *bind.WatchOpts, sink chan<- *IAdminGovernorAdded) (event.Subscription, error) { +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_IAccessControlEnumerable *IAccessControlEnumerableFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *IAccessControlEnumerableRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } - logs, sub, err := _IAdmin.contract.WatchLogs(opts, "GovernorAdded") + logs, sub, err := _IAccessControlEnumerable.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) if err != nil { return nil, err } @@ -9508,8 +8682,8 @@ func (_IAdmin *IAdminFilterer) WatchGovernorAdded(opts *bind.WatchOpts, sink cha select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(IAdminGovernorAdded) - if err := _IAdmin.contract.UnpackLog(event, "GovernorAdded", log); err != nil { + event := new(IAccessControlEnumerableRoleGranted) + if err := _IAccessControlEnumerable.contract.UnpackLog(event, "RoleGranted", log); err != nil { return err } event.Raw = log @@ -9530,21 +8704,21 @@ func (_IAdmin *IAdminFilterer) WatchGovernorAdded(opts *bind.WatchOpts, sink cha }), nil } -// ParseGovernorAdded is a log parse operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. +// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. // -// Solidity: event GovernorAdded(address governor) -func (_IAdmin *IAdminFilterer) ParseGovernorAdded(log types.Log) (*IAdminGovernorAdded, error) { - event := new(IAdminGovernorAdded) - if err := _IAdmin.contract.UnpackLog(event, "GovernorAdded", log); err != nil { +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_IAccessControlEnumerable *IAccessControlEnumerableFilterer) ParseRoleGranted(log types.Log) (*IAccessControlEnumerableRoleGranted, error) { + event := new(IAccessControlEnumerableRoleGranted) + if err := _IAccessControlEnumerable.contract.UnpackLog(event, "RoleGranted", log); err != nil { return nil, err } event.Raw = log return event, nil } -// IAdminGovernorRemovedIterator is returned from FilterGovernorRemoved and is used to iterate over the raw logs and unpacked data for GovernorRemoved events raised by the IAdmin contract. -type IAdminGovernorRemovedIterator struct { - Event *IAdminGovernorRemoved // Event containing the contract specifics and raw log +// IAccessControlEnumerableRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the IAccessControlEnumerable contract. +type IAccessControlEnumerableRoleRevokedIterator struct { + Event *IAccessControlEnumerableRoleRevoked // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -9558,7 +8732,7 @@ type IAdminGovernorRemovedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *IAdminGovernorRemovedIterator) Next() bool { +func (it *IAccessControlEnumerableRoleRevokedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -9567,7 +8741,7 @@ func (it *IAdminGovernorRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(IAdminGovernorRemoved) + it.Event = new(IAccessControlEnumerableRoleRevoked) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -9582,7 +8756,7 @@ func (it *IAdminGovernorRemovedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(IAdminGovernorRemoved) + it.Event = new(IAccessControlEnumerableRoleRevoked) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -9598,41 +8772,69 @@ func (it *IAdminGovernorRemovedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *IAdminGovernorRemovedIterator) Error() error { +func (it *IAccessControlEnumerableRoleRevokedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *IAdminGovernorRemovedIterator) Close() error { +func (it *IAccessControlEnumerableRoleRevokedIterator) Close() error { it.sub.Unsubscribe() return nil } -// IAdminGovernorRemoved represents a GovernorRemoved event raised by the IAdmin contract. -type IAdminGovernorRemoved struct { - Governor common.Address - Raw types.Log // Blockchain specific contextual infos +// IAccessControlEnumerableRoleRevoked represents a RoleRevoked event raised by the IAccessControlEnumerable contract. +type IAccessControlEnumerableRoleRevoked struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos } -// FilterGovernorRemoved is a free log retrieval operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. +// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. // -// Solidity: event GovernorRemoved(address governor) -func (_IAdmin *IAdminFilterer) FilterGovernorRemoved(opts *bind.FilterOpts) (*IAdminGovernorRemovedIterator, error) { +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_IAccessControlEnumerable *IAccessControlEnumerableFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*IAccessControlEnumerableRoleRevokedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } - logs, sub, err := _IAdmin.contract.FilterLogs(opts, "GovernorRemoved") + logs, sub, err := _IAccessControlEnumerable.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) if err != nil { return nil, err } - return &IAdminGovernorRemovedIterator{contract: _IAdmin.contract, event: "GovernorRemoved", logs: logs, sub: sub}, nil + return &IAccessControlEnumerableRoleRevokedIterator{contract: _IAccessControlEnumerable.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil } -// WatchGovernorRemoved is a free log subscription operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. +// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. // -// Solidity: event GovernorRemoved(address governor) -func (_IAdmin *IAdminFilterer) WatchGovernorRemoved(opts *bind.WatchOpts, sink chan<- *IAdminGovernorRemoved) (event.Subscription, error) { +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_IAccessControlEnumerable *IAccessControlEnumerableFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *IAccessControlEnumerableRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } - logs, sub, err := _IAdmin.contract.WatchLogs(opts, "GovernorRemoved") + logs, sub, err := _IAccessControlEnumerable.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) if err != nil { return nil, err } @@ -9642,8 +8844,8 @@ func (_IAdmin *IAdminFilterer) WatchGovernorRemoved(opts *bind.WatchOpts, sink c select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(IAdminGovernorRemoved) - if err := _IAdmin.contract.UnpackLog(event, "GovernorRemoved", log); err != nil { + event := new(IAccessControlEnumerableRoleRevoked) + if err := _IAccessControlEnumerable.contract.UnpackLog(event, "RoleRevoked", log); err != nil { return err } event.Raw = log @@ -9664,155 +8866,244 @@ func (_IAdmin *IAdminFilterer) WatchGovernorRemoved(opts *bind.WatchOpts, sink c }), nil } -// ParseGovernorRemoved is a log parse operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. -// -// Solidity: event GovernorRemoved(address governor) -func (_IAdmin *IAdminFilterer) ParseGovernorRemoved(log types.Log) (*IAdminGovernorRemoved, error) { - event := new(IAdminGovernorRemoved) - if err := _IAdmin.contract.UnpackLog(event, "GovernorRemoved", log); err != nil { +// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_IAccessControlEnumerable *IAccessControlEnumerableFilterer) ParseRoleRevoked(log types.Log) (*IAccessControlEnumerableRoleRevoked, error) { + event := new(IAccessControlEnumerableRoleRevoked) + if err := _IAccessControlEnumerable.contract.UnpackLog(event, "RoleRevoked", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IAdminMetaData contains all meta data concerning the IAdmin contract. +var IAdminMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "b250fe6b": "setChainGasAmount(uint256)", + "b13aa2d6": "setProtocolFeeRate(uint256)", + "06f333f2": "sweepProtocolFees(address,address)", + }, +} + +// IAdminABI is the input ABI used to generate the binding from. +// Deprecated: Use IAdminMetaData.ABI instead. +var IAdminABI = IAdminMetaData.ABI + +// Deprecated: Use IAdminMetaData.Sigs instead. +// IAdminFuncSigs maps the 4-byte function signature to its string representation. +var IAdminFuncSigs = IAdminMetaData.Sigs + +// IAdmin is an auto generated Go binding around an Ethereum contract. +type IAdmin struct { + IAdminCaller // Read-only binding to the contract + IAdminTransactor // Write-only binding to the contract + IAdminFilterer // Log filterer for contract events +} + +// IAdminCaller is an auto generated read-only Go binding around an Ethereum contract. +type IAdminCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IAdminTransactor is an auto generated write-only Go binding around an Ethereum contract. +type IAdminTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IAdminFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IAdminFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IAdminSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type IAdminSession struct { + Contract *IAdmin // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IAdminCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type IAdminCallerSession struct { + Contract *IAdminCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// IAdminTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type IAdminTransactorSession struct { + Contract *IAdminTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IAdminRaw is an auto generated low-level Go binding around an Ethereum contract. +type IAdminRaw struct { + Contract *IAdmin // Generic contract binding to access the raw methods on +} + +// IAdminCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IAdminCallerRaw struct { + Contract *IAdminCaller // Generic read-only contract binding to access the raw methods on +} + +// IAdminTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IAdminTransactorRaw struct { + Contract *IAdminTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewIAdmin creates a new instance of IAdmin, bound to a specific deployed contract. +func NewIAdmin(address common.Address, backend bind.ContractBackend) (*IAdmin, error) { + contract, err := bindIAdmin(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &IAdmin{IAdminCaller: IAdminCaller{contract: contract}, IAdminTransactor: IAdminTransactor{contract: contract}, IAdminFilterer: IAdminFilterer{contract: contract}}, nil +} + +// NewIAdminCaller creates a new read-only instance of IAdmin, bound to a specific deployed contract. +func NewIAdminCaller(address common.Address, caller bind.ContractCaller) (*IAdminCaller, error) { + contract, err := bindIAdmin(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &IAdminCaller{contract: contract}, nil +} + +// NewIAdminTransactor creates a new write-only instance of IAdmin, bound to a specific deployed contract. +func NewIAdminTransactor(address common.Address, transactor bind.ContractTransactor) (*IAdminTransactor, error) { + contract, err := bindIAdmin(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &IAdminTransactor{contract: contract}, nil +} + +// NewIAdminFilterer creates a new log filterer instance of IAdmin, bound to a specific deployed contract. +func NewIAdminFilterer(address common.Address, filterer bind.ContractFilterer) (*IAdminFilterer, error) { + contract, err := bindIAdmin(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &IAdminFilterer{contract: contract}, nil +} + +// bindIAdmin binds a generic wrapper to an already deployed contract. +func bindIAdmin(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := IAdminMetaData.GetAbi() + if err != nil { return nil, err } - event.Raw = log - return event, nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } -// IAdminGuardAddedIterator is returned from FilterGuardAdded and is used to iterate over the raw logs and unpacked data for GuardAdded events raised by the IAdmin contract. -type IAdminGuardAddedIterator struct { - Event *IAdminGuardAdded // Event containing the contract specifics and raw log +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IAdmin *IAdminRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IAdmin.Contract.IAdminCaller.contract.Call(opts, result, method, params...) +} - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IAdmin *IAdminRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IAdmin.Contract.IAdminTransactor.contract.Transfer(opts) +} - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// Transact invokes the (paid) contract method with params as input values. +func (_IAdmin *IAdminRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IAdmin.Contract.IAdminTransactor.contract.Transact(opts, method, params...) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *IAdminGuardAddedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(IAdminGuardAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IAdmin *IAdminCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IAdmin.Contract.contract.Call(opts, result, method, params...) +} - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(IAdminGuardAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IAdmin *IAdminTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IAdmin.Contract.contract.Transfer(opts) +} - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } +// Transact invokes the (paid) contract method with params as input values. +func (_IAdmin *IAdminTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IAdmin.Contract.contract.Transact(opts, method, params...) } -// Error returns any retrieval or parsing error occurred during filtering. -func (it *IAdminGuardAddedIterator) Error() error { - return it.fail +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_IAdmin *IAdminTransactor) SetChainGasAmount(opts *bind.TransactOpts, newChainGasAmount *big.Int) (*types.Transaction, error) { + return _IAdmin.contract.Transact(opts, "setChainGasAmount", newChainGasAmount) } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *IAdminGuardAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_IAdmin *IAdminSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { + return _IAdmin.Contract.SetChainGasAmount(&_IAdmin.TransactOpts, newChainGasAmount) } -// IAdminGuardAdded represents a GuardAdded event raised by the IAdmin contract. -type IAdminGuardAdded struct { - Guard common.Address - Raw types.Log // Blockchain specific contextual infos +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_IAdmin *IAdminTransactorSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { + return _IAdmin.Contract.SetChainGasAmount(&_IAdmin.TransactOpts, newChainGasAmount) } -// FilterGuardAdded is a free log retrieval operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. // -// Solidity: event GuardAdded(address guard) -func (_IAdmin *IAdminFilterer) FilterGuardAdded(opts *bind.FilterOpts) (*IAdminGuardAddedIterator, error) { +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_IAdmin *IAdminTransactor) SetProtocolFeeRate(opts *bind.TransactOpts, newFeeRate *big.Int) (*types.Transaction, error) { + return _IAdmin.contract.Transact(opts, "setProtocolFeeRate", newFeeRate) +} - logs, sub, err := _IAdmin.contract.FilterLogs(opts, "GuardAdded") - if err != nil { - return nil, err - } - return &IAdminGuardAddedIterator{contract: _IAdmin.contract, event: "GuardAdded", logs: logs, sub: sub}, nil +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. +// +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_IAdmin *IAdminSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { + return _IAdmin.Contract.SetProtocolFeeRate(&_IAdmin.TransactOpts, newFeeRate) } -// WatchGuardAdded is a free log subscription operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. // -// Solidity: event GuardAdded(address guard) -func (_IAdmin *IAdminFilterer) WatchGuardAdded(opts *bind.WatchOpts, sink chan<- *IAdminGuardAdded) (event.Subscription, error) { +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_IAdmin *IAdminTransactorSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { + return _IAdmin.Contract.SetProtocolFeeRate(&_IAdmin.TransactOpts, newFeeRate) +} - logs, sub, err := _IAdmin.contract.WatchLogs(opts, "GuardAdded") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(IAdminGuardAdded) - if err := _IAdmin.contract.UnpackLog(event, "GuardAdded", log); err != nil { - return err - } - event.Raw = log +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_IAdmin *IAdminTransactor) SweepProtocolFees(opts *bind.TransactOpts, token common.Address, recipient common.Address) (*types.Transaction, error) { + return _IAdmin.contract.Transact(opts, "sweepProtocolFees", token, recipient) +} - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_IAdmin *IAdminSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { + return _IAdmin.Contract.SweepProtocolFees(&_IAdmin.TransactOpts, token, recipient) } -// ParseGuardAdded is a log parse operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. // -// Solidity: event GuardAdded(address guard) -func (_IAdmin *IAdminFilterer) ParseGuardAdded(log types.Log) (*IAdminGuardAdded, error) { - event := new(IAdminGuardAdded) - if err := _IAdmin.contract.UnpackLog(event, "GuardAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_IAdmin *IAdminTransactorSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { + return _IAdmin.Contract.SweepProtocolFees(&_IAdmin.TransactOpts, token, recipient) } -// IAdminGuardRemovedIterator is returned from FilterGuardRemoved and is used to iterate over the raw logs and unpacked data for GuardRemoved events raised by the IAdmin contract. -type IAdminGuardRemovedIterator struct { - Event *IAdminGuardRemoved // Event containing the contract specifics and raw log +// IAdminChainGasAmountUpdatedIterator is returned from FilterChainGasAmountUpdated and is used to iterate over the raw logs and unpacked data for ChainGasAmountUpdated events raised by the IAdmin contract. +type IAdminChainGasAmountUpdatedIterator struct { + Event *IAdminChainGasAmountUpdated // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -9826,7 +9117,7 @@ type IAdminGuardRemovedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *IAdminGuardRemovedIterator) Next() bool { +func (it *IAdminChainGasAmountUpdatedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -9835,7 +9126,7 @@ func (it *IAdminGuardRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(IAdminGuardRemoved) + it.Event = new(IAdminChainGasAmountUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -9850,7 +9141,7 @@ func (it *IAdminGuardRemovedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(IAdminGuardRemoved) + it.Event = new(IAdminChainGasAmountUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -9866,41 +9157,42 @@ func (it *IAdminGuardRemovedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *IAdminGuardRemovedIterator) Error() error { +func (it *IAdminChainGasAmountUpdatedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *IAdminGuardRemovedIterator) Close() error { +func (it *IAdminChainGasAmountUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -// IAdminGuardRemoved represents a GuardRemoved event raised by the IAdmin contract. -type IAdminGuardRemoved struct { - Guard common.Address - Raw types.Log // Blockchain specific contextual infos +// IAdminChainGasAmountUpdated represents a ChainGasAmountUpdated event raised by the IAdmin contract. +type IAdminChainGasAmountUpdated struct { + OldChainGasAmount *big.Int + NewChainGasAmount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterGuardRemoved is a free log retrieval operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// FilterChainGasAmountUpdated is a free log retrieval operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event GuardRemoved(address guard) -func (_IAdmin *IAdminFilterer) FilterGuardRemoved(opts *bind.FilterOpts) (*IAdminGuardRemovedIterator, error) { +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_IAdmin *IAdminFilterer) FilterChainGasAmountUpdated(opts *bind.FilterOpts) (*IAdminChainGasAmountUpdatedIterator, error) { - logs, sub, err := _IAdmin.contract.FilterLogs(opts, "GuardRemoved") + logs, sub, err := _IAdmin.contract.FilterLogs(opts, "ChainGasAmountUpdated") if err != nil { return nil, err } - return &IAdminGuardRemovedIterator{contract: _IAdmin.contract, event: "GuardRemoved", logs: logs, sub: sub}, nil + return &IAdminChainGasAmountUpdatedIterator{contract: _IAdmin.contract, event: "ChainGasAmountUpdated", logs: logs, sub: sub}, nil } -// WatchGuardRemoved is a free log subscription operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// WatchChainGasAmountUpdated is a free log subscription operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event GuardRemoved(address guard) -func (_IAdmin *IAdminFilterer) WatchGuardRemoved(opts *bind.WatchOpts, sink chan<- *IAdminGuardRemoved) (event.Subscription, error) { +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_IAdmin *IAdminFilterer) WatchChainGasAmountUpdated(opts *bind.WatchOpts, sink chan<- *IAdminChainGasAmountUpdated) (event.Subscription, error) { - logs, sub, err := _IAdmin.contract.WatchLogs(opts, "GuardRemoved") + logs, sub, err := _IAdmin.contract.WatchLogs(opts, "ChainGasAmountUpdated") if err != nil { return nil, err } @@ -9910,8 +9202,8 @@ func (_IAdmin *IAdminFilterer) WatchGuardRemoved(opts *bind.WatchOpts, sink chan select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(IAdminGuardRemoved) - if err := _IAdmin.contract.UnpackLog(event, "GuardRemoved", log); err != nil { + event := new(IAdminChainGasAmountUpdated) + if err := _IAdmin.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { return err } event.Raw = log @@ -9932,21 +9224,21 @@ func (_IAdmin *IAdminFilterer) WatchGuardRemoved(opts *bind.WatchOpts, sink chan }), nil } -// ParseGuardRemoved is a log parse operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// ParseChainGasAmountUpdated is a log parse operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event GuardRemoved(address guard) -func (_IAdmin *IAdminFilterer) ParseGuardRemoved(log types.Log) (*IAdminGuardRemoved, error) { - event := new(IAdminGuardRemoved) - if err := _IAdmin.contract.UnpackLog(event, "GuardRemoved", log); err != nil { +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_IAdmin *IAdminFilterer) ParseChainGasAmountUpdated(log types.Log) (*IAdminChainGasAmountUpdated, error) { + event := new(IAdminChainGasAmountUpdated) + if err := _IAdmin.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -// IAdminRelayerAddedIterator is returned from FilterRelayerAdded and is used to iterate over the raw logs and unpacked data for RelayerAdded events raised by the IAdmin contract. -type IAdminRelayerAddedIterator struct { - Event *IAdminRelayerAdded // Event containing the contract specifics and raw log +// IAdminFeeRateUpdatedIterator is returned from FilterFeeRateUpdated and is used to iterate over the raw logs and unpacked data for FeeRateUpdated events raised by the IAdmin contract. +type IAdminFeeRateUpdatedIterator struct { + Event *IAdminFeeRateUpdated // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -9960,7 +9252,7 @@ type IAdminRelayerAddedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *IAdminRelayerAddedIterator) Next() bool { +func (it *IAdminFeeRateUpdatedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -9969,7 +9261,7 @@ func (it *IAdminRelayerAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(IAdminRelayerAdded) + it.Event = new(IAdminFeeRateUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -9984,7 +9276,7 @@ func (it *IAdminRelayerAddedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(IAdminRelayerAdded) + it.Event = new(IAdminFeeRateUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -10000,41 +9292,42 @@ func (it *IAdminRelayerAddedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *IAdminRelayerAddedIterator) Error() error { +func (it *IAdminFeeRateUpdatedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *IAdminRelayerAddedIterator) Close() error { +func (it *IAdminFeeRateUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -// IAdminRelayerAdded represents a RelayerAdded event raised by the IAdmin contract. -type IAdminRelayerAdded struct { - Relayer common.Address - Raw types.Log // Blockchain specific contextual infos +// IAdminFeeRateUpdated represents a FeeRateUpdated event raised by the IAdmin contract. +type IAdminFeeRateUpdated struct { + OldFeeRate *big.Int + NewFeeRate *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterRelayerAdded is a free log retrieval operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// FilterFeeRateUpdated is a free log retrieval operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. // -// Solidity: event RelayerAdded(address relayer) -func (_IAdmin *IAdminFilterer) FilterRelayerAdded(opts *bind.FilterOpts) (*IAdminRelayerAddedIterator, error) { +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_IAdmin *IAdminFilterer) FilterFeeRateUpdated(opts *bind.FilterOpts) (*IAdminFeeRateUpdatedIterator, error) { - logs, sub, err := _IAdmin.contract.FilterLogs(opts, "RelayerAdded") + logs, sub, err := _IAdmin.contract.FilterLogs(opts, "FeeRateUpdated") if err != nil { return nil, err } - return &IAdminRelayerAddedIterator{contract: _IAdmin.contract, event: "RelayerAdded", logs: logs, sub: sub}, nil + return &IAdminFeeRateUpdatedIterator{contract: _IAdmin.contract, event: "FeeRateUpdated", logs: logs, sub: sub}, nil } -// WatchRelayerAdded is a free log subscription operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// WatchFeeRateUpdated is a free log subscription operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. // -// Solidity: event RelayerAdded(address relayer) -func (_IAdmin *IAdminFilterer) WatchRelayerAdded(opts *bind.WatchOpts, sink chan<- *IAdminRelayerAdded) (event.Subscription, error) { +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_IAdmin *IAdminFilterer) WatchFeeRateUpdated(opts *bind.WatchOpts, sink chan<- *IAdminFeeRateUpdated) (event.Subscription, error) { - logs, sub, err := _IAdmin.contract.WatchLogs(opts, "RelayerAdded") + logs, sub, err := _IAdmin.contract.WatchLogs(opts, "FeeRateUpdated") if err != nil { return nil, err } @@ -10044,8 +9337,8 @@ func (_IAdmin *IAdminFilterer) WatchRelayerAdded(opts *bind.WatchOpts, sink chan select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(IAdminRelayerAdded) - if err := _IAdmin.contract.UnpackLog(event, "RelayerAdded", log); err != nil { + event := new(IAdminFeeRateUpdated) + if err := _IAdmin.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { return err } event.Raw = log @@ -10066,21 +9359,21 @@ func (_IAdmin *IAdminFilterer) WatchRelayerAdded(opts *bind.WatchOpts, sink chan }), nil } -// ParseRelayerAdded is a log parse operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// ParseFeeRateUpdated is a log parse operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. // -// Solidity: event RelayerAdded(address relayer) -func (_IAdmin *IAdminFilterer) ParseRelayerAdded(log types.Log) (*IAdminRelayerAdded, error) { - event := new(IAdminRelayerAdded) - if err := _IAdmin.contract.UnpackLog(event, "RelayerAdded", log); err != nil { +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_IAdmin *IAdminFilterer) ParseFeeRateUpdated(log types.Log) (*IAdminFeeRateUpdated, error) { + event := new(IAdminFeeRateUpdated) + if err := _IAdmin.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -// IAdminRelayerRemovedIterator is returned from FilterRelayerRemoved and is used to iterate over the raw logs and unpacked data for RelayerRemoved events raised by the IAdmin contract. -type IAdminRelayerRemovedIterator struct { - Event *IAdminRelayerRemoved // Event containing the contract specifics and raw log +// IAdminFeesSweptIterator is returned from FilterFeesSwept and is used to iterate over the raw logs and unpacked data for FeesSwept events raised by the IAdmin contract. +type IAdminFeesSweptIterator struct { + Event *IAdminFeesSwept // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -10094,7 +9387,7 @@ type IAdminRelayerRemovedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *IAdminRelayerRemovedIterator) Next() bool { +func (it *IAdminFeesSweptIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -10103,7 +9396,7 @@ func (it *IAdminRelayerRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(IAdminRelayerRemoved) + it.Event = new(IAdminFeesSwept) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -10118,7 +9411,7 @@ func (it *IAdminRelayerRemovedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(IAdminRelayerRemoved) + it.Event = new(IAdminFeesSwept) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -10134,41 +9427,43 @@ func (it *IAdminRelayerRemovedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *IAdminRelayerRemovedIterator) Error() error { +func (it *IAdminFeesSweptIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *IAdminRelayerRemovedIterator) Close() error { +func (it *IAdminFeesSweptIterator) Close() error { it.sub.Unsubscribe() return nil } -// IAdminRelayerRemoved represents a RelayerRemoved event raised by the IAdmin contract. -type IAdminRelayerRemoved struct { - Relayer common.Address - Raw types.Log // Blockchain specific contextual infos +// IAdminFeesSwept represents a FeesSwept event raised by the IAdmin contract. +type IAdminFeesSwept struct { + Token common.Address + Recipient common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterRelayerRemoved is a free log retrieval operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// FilterFeesSwept is a free log retrieval operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. // -// Solidity: event RelayerRemoved(address relayer) -func (_IAdmin *IAdminFilterer) FilterRelayerRemoved(opts *bind.FilterOpts) (*IAdminRelayerRemovedIterator, error) { +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_IAdmin *IAdminFilterer) FilterFeesSwept(opts *bind.FilterOpts) (*IAdminFeesSweptIterator, error) { - logs, sub, err := _IAdmin.contract.FilterLogs(opts, "RelayerRemoved") + logs, sub, err := _IAdmin.contract.FilterLogs(opts, "FeesSwept") if err != nil { return nil, err } - return &IAdminRelayerRemovedIterator{contract: _IAdmin.contract, event: "RelayerRemoved", logs: logs, sub: sub}, nil + return &IAdminFeesSweptIterator{contract: _IAdmin.contract, event: "FeesSwept", logs: logs, sub: sub}, nil } -// WatchRelayerRemoved is a free log subscription operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// WatchFeesSwept is a free log subscription operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. // -// Solidity: event RelayerRemoved(address relayer) -func (_IAdmin *IAdminFilterer) WatchRelayerRemoved(opts *bind.WatchOpts, sink chan<- *IAdminRelayerRemoved) (event.Subscription, error) { +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_IAdmin *IAdminFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink chan<- *IAdminFeesSwept) (event.Subscription, error) { - logs, sub, err := _IAdmin.contract.WatchLogs(opts, "RelayerRemoved") + logs, sub, err := _IAdmin.contract.WatchLogs(opts, "FeesSwept") if err != nil { return nil, err } @@ -10178,8 +9473,8 @@ func (_IAdmin *IAdminFilterer) WatchRelayerRemoved(opts *bind.WatchOpts, sink ch select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(IAdminRelayerRemoved) - if err := _IAdmin.contract.UnpackLog(event, "RelayerRemoved", log); err != nil { + event := new(IAdminFeesSwept) + if err := _IAdmin.contract.UnpackLog(event, "FeesSwept", log); err != nil { return err } event.Raw = log @@ -10200,12 +9495,12 @@ func (_IAdmin *IAdminFilterer) WatchRelayerRemoved(opts *bind.WatchOpts, sink ch }), nil } -// ParseRelayerRemoved is a log parse operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// ParseFeesSwept is a log parse operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. // -// Solidity: event RelayerRemoved(address relayer) -func (_IAdmin *IAdminFilterer) ParseRelayerRemoved(log types.Log) (*IAdminRelayerRemoved, error) { - event := new(IAdminRelayerRemoved) - if err := _IAdmin.contract.UnpackLog(event, "RelayerRemoved", log); err != nil { +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_IAdmin *IAdminFilterer) ParseFeesSwept(log types.Log) (*IAdminFeesSwept, error) { + event := new(IAdminFeesSwept) + if err := _IAdmin.contract.UnpackLog(event, "FeesSwept", log); err != nil { return nil, err } event.Raw = log @@ -12581,7 +11876,7 @@ func (_IFastBridge *IFastBridgeFilterer) ParseBridgeRequested(log types.Log) (*I // SafeERC20MetaData contains all meta data concerning the SafeERC20 contract. var SafeERC20MetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"currentAllowance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestedDecrease\",\"type\":\"uint256\"}],\"name\":\"SafeERC20FailedDecreaseAllowance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"}]", - Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122005400bbfbb5fd0089c6f9c2d1b90d14696e5ecb30fcae08fe245f0ac1ce92b2564736f6c63430008140033", + Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c6ed48084fea72d6c821edce7a5b7849414ac26c2e14da8d9184448698b54a2964736f6c63430008140033", } // SafeERC20ABI is the input ABI used to generate the binding from. @@ -12754,7 +12049,7 @@ func (_SafeERC20 *SafeERC20TransactorRaw) Transact(opts *bind.TransactOpts, meth // UniversalTokenLibMetaData contains all meta data concerning the UniversalTokenLib contract. var UniversalTokenLibMetaData = &bind.MetaData{ ABI: "[]", - Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220e0b99ca0473a4b615794462912a21c7b61d5dc8961d7074cb84653b63782c78c64736f6c63430008140033", + Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122054dc3657c8fde761d2c05cf2a9b92991c4c740565f4124cc2177c16ea935345764736f6c63430008140033", } // UniversalTokenLibABI is the input ABI used to generate the binding from. diff --git a/services/rfq/contracts/fastbridge/fastbridge.contractinfo.json b/services/rfq/contracts/fastbridge/fastbridge.contractinfo.json index 5b393396fa..740c11b54c 100644 --- a/services/rfq/contracts/fastbridge/fastbridge.contractinfo.json +++ b/services/rfq/contracts/fastbridge/fastbridge.contractinfo.json @@ -1 +1 @@ -{"solidity/FastBridge.sol:AccessControl":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Contract module that allows children to implement role-based access control mechanisms. This is a lightweight version that doesn't allow enumerating role members except through off-chain means by accessing the contract event logs. Some applications may benefit from on-chain enumerability, for those cases see {AccessControlEnumerable}. Roles are referred to by their `bytes32` identifier. These should be exposed in the external API and be unique. The best way to achieve this is by using `public constant` hash digests: ```solidity bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\"); ``` Roles can be used to represent a set of permissions. To restrict access to a function call, use {hasRole}: ```solidity function foo() public { require(hasRole(MY_ROLE, msg.sender)); ... } ``` Roles can be granted and revoked dynamically via the {grantRole} and {revokeRole} functions. Each role has an associated admin role, and only accounts that have a role's admin role can call {grantRole} and {revokeRole}. By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using {_setRoleAdmin}. WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} to enforce additional security measures for this role.","errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Contract module that allows children to implement role-based access control mechanisms. This is a lightweight version that doesn't allow enumerating role members except through off-chain means by accessing the contract event logs. Some applications may benefit from on-chain enumerability, for those cases see {AccessControlEnumerable}. Roles are referred to by their `bytes32` identifier. These should be exposed in the external API and be unique. The best way to achieve this is by using `public constant` hash digests: ```solidity bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\"); ``` Roles can be used to represent a set of permissions. To restrict access to a function call, use {hasRole}: ```solidity function foo() public { require(hasRole(MY_ROLE, msg.sender)); ... } ``` Roles can be granted and revoked dynamically via the {grantRole} and {revokeRole} functions. Each role has an associated admin role, and only accounts that have a role's admin role can call {grantRole} and {revokeRole}. By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using {_setRoleAdmin}. WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} to enforce additional security measures for this role.\",\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"AccessControl\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x5838f2ff3b1c4e6b40f973a29cce9f16871bd7a03add5aeeb7f876df39e92167\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://220c9bc7c31596b7d0ad7806037a3ebaed6c271c84df15e3789d850deef3fb1a\",\"dweb:/ipfs/QmU3xjtrAqz9fBLJKHC8Q4LCXpTi77i2oJJbu5Q5Ex2h4J\"]}},\"version\":1}"},"hashes":{"DEFAULT_ADMIN_ROLE()":"a217fddf","getRoleAdmin(bytes32)":"248a9ca3","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","supportsInterface(bytes4)":"01ffc9a7"}},"solidity/FastBridge.sol:Address":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220d80dee42c3c64f0baf51820376f96b740ea0cfbed8a9b603c3bfbdaab286bbc964736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220d80dee42c3c64f0baf51820376f96b740ea0cfbed8a9b603c3bfbdaab286bbc964736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"16176:6066:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;16176:6066:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"16176:6066:0:-:0;;;;;;;;","abiDefinition":[{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Collection of functions related to the address type","errors":{"AddressEmptyCode(address)":[{"details":"There's no code at `target` (it is not a contract)."}],"AddressInsufficientBalance(address)":[{"details":"The ETH balance of the account is not enough to perform the operation."}],"FailedInnerCall()":[{"details":"A call to an address target failed. The target may have reverted."}]},"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"}],\"devdoc\":{\"details\":\"Collection of functions related to the address type\",\"errors\":{\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"AddressInsufficientBalance(address)\":[{\"details\":\"The ETH balance of the account is not enough to perform the operation.\"}],\"FailedInnerCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}]},\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"Address\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x5838f2ff3b1c4e6b40f973a29cce9f16871bd7a03add5aeeb7f876df39e92167\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://220c9bc7c31596b7d0ad7806037a3ebaed6c271c84df15e3789d850deef3fb1a\",\"dweb:/ipfs/QmU3xjtrAqz9fBLJKHC8Q4LCXpTi77i2oJJbu5Q5Ex2h4J\"]}},\"version\":1}"},"hashes":{}},"solidity/FastBridge.sol:Admin":{"code":"0x608060405234801561001057600080fd5b50604051620015cf380380620015cf833981016040819052610031916100ef565b61003c600082610043565b505061011f565b6000828152602081815260408083206001600160a01b038516845290915281205460ff166100e5576000838152602081815260408083206001600160a01b03861684529091529020805460ff1916600117905561009d3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016100e9565b5060005b92915050565b60006020828403121561010157600080fd5b81516001600160a01b038116811461011857600080fd5b9392505050565b6114a0806200012f6000396000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c8063926d7d7f116100e3578063ccc574901161008c578063dd39f00d11610066578063dd39f00d146103b3578063e00a83e0146103c6578063eecdac88146103cf57600080fd5b8063ccc5749014610359578063d547741f14610380578063dcf844a71461039357600080fd5b8063b250fe6b116100bd578063b250fe6b14610329578063b62350161461033c578063bf333f2c1461034f57600080fd5b8063926d7d7f146102e7578063a217fddf1461030e578063b13aa2d61461031657600080fd5b806336568abe1161014557806360f0a5ac1161011f57806360f0a5ac1461027d5780636913a63c1461029057806391d14854146102a357600080fd5b806336568abe1461024e5780633c4a25d01461026157806358f858801461027457600080fd5b80630f5f6ed7116101765780630f5f6ed71461020f578063248a9ca3146102185780632f2ff15d1461023b57600080fd5b806301ffc9a71461019d57806303ed0ee5146101c557806306f333f2146101fa575b600080fd5b6101b06101ab366004611324565b6103e2565b60405190151581526020015b60405180910390f35b6101ec7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b6040519081526020016101bc565b61020d61020836600461138f565b61047b565b005b6101ec61271081565b6101ec6102263660046113c2565b60009081526020819052604090206001015490565b61020d6102493660046113db565b6105da565b61020d61025c3660046113db565b610605565b61020d61026f3660046113fe565b610663565b6101ec60015481565b61020d61028b3660046113fe565b610716565b61020d61029e3660046113fe565b6107c2565b6101b06102b13660046113db565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6101ec7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b6101ec600081565b61020d6103243660046113c2565b61086e565b61020d6103373660046113c2565b6109b8565b61020d61034a3660046113fe565b610a8e565b6101ec620f424081565b6101ec7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b61020d61038e3660046113db565b610b3a565b6101ec6103a13660046113fe565b60026020526000908152604090205481565b61020d6103c13660046113fe565b610b5f565b6101ec60035481565b61020d6103dd3660046113fe565b610c0b565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061047557507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16610518576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600260205260408120549081900361054b57505050565b73ffffffffffffffffffffffffffffffffffffffff831660008181526002602052604081205561057c908383610cb7565b6040805173ffffffffffffffffffffffffffffffffffffffff8086168252841660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b5050565b6000828152602081905260409020600101546105f581610e0e565b6105ff8383610e1b565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610654576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61065e8282610f17565b505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661069e57600080fd5b6106c87f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5582610e1b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5906020015b60405180910390a150565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661075157600080fd5b61077b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc482610f17565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b9060200161070b565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166107fd57600080fd5b6108277f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d82610e1b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f599060200161070b565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16610906576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f720000000000000000604482015260640161050f565b612710811115610972576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d617800000000000000000000000000000000604482015260640161050f565b600180549082905560408051828152602081018490527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a15050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16610a50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f720000000000000000604482015260640161050f565b600380549082905560408051828152602081018490527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa91016109ac565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610ac957600080fd5b610af37f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d82610f17565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d0489060200161070b565b600082815260208190526040902060010154610b5581610e0e565b6105ff8383610f17565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610b9a57600080fd5b610bc47fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc482610e1b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c59060200161070b565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610c4657600080fd5b610c707f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5582610f17565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b9060200161070b565b3073ffffffffffffffffffffffffffffffffffffffff831603610cd957505050565b80600003610ce657505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff841601610ded5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610d7d576040519150601f19603f3d011682016040523d82523d6000602084013e610d82565b606091505b50509050806105ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c656400000000000000000000000000604482015260640161050f565b61065e73ffffffffffffffffffffffffffffffffffffffff84168383610fd2565b610e18813361105f565b50565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16610f0f5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610ead3390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610475565b506000610475565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff1615610f0f5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610475565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261065e9084906110e5565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166105d6576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024810183905260440161050f565b600061110773ffffffffffffffffffffffffffffffffffffffff84168361117b565b9050805160001415801561112c57508080602001905181019061112a9190611419565b155b1561065e576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161050f565b606061118983836000611190565b9392505050565b6060814710156111ce576040517fcd78605900000000000000000000000000000000000000000000000000000000815230600482015260240161050f565b6000808573ffffffffffffffffffffffffffffffffffffffff1684866040516111f7919061143b565b60006040518083038185875af1925050503d8060008114611234576040519150601f19603f3d011682016040523d82523d6000602084013e611239565b606091505b5091509150611249868383611253565b9695505050505050565b60608261126857611263826112e2565b611189565b815115801561128c575073ffffffffffffffffffffffffffffffffffffffff84163b155b156112db576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015260240161050f565b5080611189565b8051156112f25780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561133657600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461118957600080fd5b803573ffffffffffffffffffffffffffffffffffffffff8116811461138a57600080fd5b919050565b600080604083850312156113a257600080fd5b6113ab83611366565b91506113b960208401611366565b90509250929050565b6000602082840312156113d457600080fd5b5035919050565b600080604083850312156113ee57600080fd5b823591506113b960208401611366565b60006020828403121561141057600080fd5b61118982611366565b60006020828403121561142b57600080fd5b8151801515811461118957600080fd5b6000825160005b8181101561145c5760208186018101518583015201611442565b50600092019182525091905056fea26469706673582212208769ea4fe17774b3d4152ad2514855ae96d78c10038c08e4a939ce0997735be264736f6c63430008140033","runtime-code":"0x608060405234801561001057600080fd5b50600436106101985760003560e01c8063926d7d7f116100e3578063ccc574901161008c578063dd39f00d11610066578063dd39f00d146103b3578063e00a83e0146103c6578063eecdac88146103cf57600080fd5b8063ccc5749014610359578063d547741f14610380578063dcf844a71461039357600080fd5b8063b250fe6b116100bd578063b250fe6b14610329578063b62350161461033c578063bf333f2c1461034f57600080fd5b8063926d7d7f146102e7578063a217fddf1461030e578063b13aa2d61461031657600080fd5b806336568abe1161014557806360f0a5ac1161011f57806360f0a5ac1461027d5780636913a63c1461029057806391d14854146102a357600080fd5b806336568abe1461024e5780633c4a25d01461026157806358f858801461027457600080fd5b80630f5f6ed7116101765780630f5f6ed71461020f578063248a9ca3146102185780632f2ff15d1461023b57600080fd5b806301ffc9a71461019d57806303ed0ee5146101c557806306f333f2146101fa575b600080fd5b6101b06101ab366004611324565b6103e2565b60405190151581526020015b60405180910390f35b6101ec7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b6040519081526020016101bc565b61020d61020836600461138f565b61047b565b005b6101ec61271081565b6101ec6102263660046113c2565b60009081526020819052604090206001015490565b61020d6102493660046113db565b6105da565b61020d61025c3660046113db565b610605565b61020d61026f3660046113fe565b610663565b6101ec60015481565b61020d61028b3660046113fe565b610716565b61020d61029e3660046113fe565b6107c2565b6101b06102b13660046113db565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6101ec7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b6101ec600081565b61020d6103243660046113c2565b61086e565b61020d6103373660046113c2565b6109b8565b61020d61034a3660046113fe565b610a8e565b6101ec620f424081565b6101ec7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b61020d61038e3660046113db565b610b3a565b6101ec6103a13660046113fe565b60026020526000908152604090205481565b61020d6103c13660046113fe565b610b5f565b6101ec60035481565b61020d6103dd3660046113fe565b610c0b565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061047557507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16610518576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600260205260408120549081900361054b57505050565b73ffffffffffffffffffffffffffffffffffffffff831660008181526002602052604081205561057c908383610cb7565b6040805173ffffffffffffffffffffffffffffffffffffffff8086168252841660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b5050565b6000828152602081905260409020600101546105f581610e0e565b6105ff8383610e1b565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610654576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61065e8282610f17565b505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661069e57600080fd5b6106c87f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5582610e1b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5906020015b60405180910390a150565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661075157600080fd5b61077b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc482610f17565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b9060200161070b565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166107fd57600080fd5b6108277f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d82610e1b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f599060200161070b565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16610906576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f720000000000000000604482015260640161050f565b612710811115610972576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d617800000000000000000000000000000000604482015260640161050f565b600180549082905560408051828152602081018490527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a15050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16610a50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f720000000000000000604482015260640161050f565b600380549082905560408051828152602081018490527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa91016109ac565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610ac957600080fd5b610af37f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d82610f17565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d0489060200161070b565b600082815260208190526040902060010154610b5581610e0e565b6105ff8383610f17565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610b9a57600080fd5b610bc47fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc482610e1b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c59060200161070b565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610c4657600080fd5b610c707f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5582610f17565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b9060200161070b565b3073ffffffffffffffffffffffffffffffffffffffff831603610cd957505050565b80600003610ce657505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff841601610ded5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610d7d576040519150601f19603f3d011682016040523d82523d6000602084013e610d82565b606091505b50509050806105ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c656400000000000000000000000000604482015260640161050f565b61065e73ffffffffffffffffffffffffffffffffffffffff84168383610fd2565b610e18813361105f565b50565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16610f0f5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610ead3390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610475565b506000610475565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff1615610f0f5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610475565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261065e9084906110e5565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166105d6576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024810183905260440161050f565b600061110773ffffffffffffffffffffffffffffffffffffffff84168361117b565b9050805160001415801561112c57508080602001905181019061112a9190611419565b155b1561065e576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161050f565b606061118983836000611190565b9392505050565b6060814710156111ce576040517fcd78605900000000000000000000000000000000000000000000000000000000815230600482015260240161050f565b6000808573ffffffffffffffffffffffffffffffffffffffff1684866040516111f7919061143b565b60006040518083038185875af1925050503d8060008114611234576040519150601f19603f3d011682016040523d82523d6000602084013e611239565b606091505b5091509150611249868383611253565b9695505050505050565b60608261126857611263826112e2565b611189565b815115801561128c575073ffffffffffffffffffffffffffffffffffffffff84163b155b156112db576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015260240161050f565b5080611189565b8051156112f25780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561133657600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461118957600080fd5b803573ffffffffffffffffffffffffffffffffffffffff8116811461138a57600080fd5b919050565b600080604083850312156113a257600080fd5b6113ab83611366565b91506113b960208401611366565b90509250929050565b6000602082840312156113d457600080fd5b5035919050565b600080604083850312156113ee57600080fd5b823591506113b960208401611366565b60006020828403121561141057600080fd5b61118982611366565b60006020828403121561142b57600080fd5b8151801515811461118957600080fd5b6000825160005b8181101561145c5760208186018101518583015201611442565b50600092019182525091905056fea26469706673582212208769ea4fe17774b3d4152ad2514855ae96d78c10038c08e4a939ce0997735be264736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"40134:3303:0:-:0;;;41254:83;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41292:38;32700:4;41323:6;41292:10;:38::i;:::-;;41254:83;40134:3303;;36647:316;36724:4;33422:12;;;;;;;;;;;-1:-1:-1;;;;;33422:29:0;;;;;;;;;;;;36740:217;;36783:6;:12;;;;;;;;;;;-1:-1:-1;;;;;36783:29:0;;;;;;;;;:36;;-1:-1:-1;;36783:36:0;36815:4;36783:36;;;36865:12;22980:10;;22901:96;36865:12;-1:-1:-1;;;;;36838:40:0;36856:7;-1:-1:-1;;;;;36838:40:0;36850:4;36838:40;;;;;;;;;;-1:-1:-1;36899:4:0;36892:11;;36740:217;-1:-1:-1;36941:5:0;36740:217;36647:316;;;;:::o;14:290:1:-;84:6;137:2;125:9;116:7;112:23;108:32;105:52;;;153:1;150;143:12;105:52;179:16;;-1:-1:-1;;;;;224:31:1;;214:42;;204:70;;270:1;267;260:12;204:70;293:5;14:290;-1:-1:-1;;;14:290:1:o;:::-;40134:3303:0;;;;;;","srcMapRuntime":"40134:3303:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33033:202;;;;;;:::i;:::-;;:::i;:::-;;;516:14:1;;509:22;491:41;;479:2;464:18;33033:202:0;;;;;;;;40292:60;;40329:23;40292:60;;;;;689:25:1;;;677:2;662:18;40292:60:0;543:177:1;42828:348:0;;;;;;:::i;:::-;;:::i;:::-;;40474:45;;40513:6;40474:45;;34278:120;;;;;;:::i;:::-;34343:7;34369:12;;;;;;;;;;:22;;;;34278:120;34694:136;;;;;;:::i;:::-;;:::i;35796:245::-;;;;;;:::i;:::-;;:::i;42127:199::-;;;;;;:::i;:::-;;:::i;40636:30::-;;;;;;41542:199;;;;;;:::i;:::-;;:::i;41747:181::-;;;;;;:::i;:::-;;:::i;33322:136::-;;;;;;:::i;:::-;33399:4;33422:12;;;;;;;;;;;:29;;;;;;;;;;;;;;;;33322:136;40222:64;;40261:25;40222:64;;32655:49;;32700:4;32655:49;;42543:279;;;;;;:::i;:::-;;:::i;43182:253::-;;;;;;:::i;:::-;;:::i;41934:187::-;;;;;;:::i;:::-;;:::i;40431:37::-;;40465:3;40431:37;;40358:66;;40398:26;40358:66;;35110:138;;;;;;:::i;:::-;;:::i;40722:47::-;;;;;;:::i;:::-;;;;;;;;;;;;;;41343:193;;;;;;:::i;:::-;;:::i;40843:29::-;;;;;;42332:205;;;;;;:::i;:::-;;:::i;33033:202::-;33118:4;33141:47;;;33156:32;33141:47;;:87;;-1:-1:-1;24946:25:0;24931:40;;;;33192:36;33134:94;33033:202;-1:-1:-1;;33033:202:0:o;42828:348::-;41190:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41159:71;;;;;;;2395:2:1;41159:71:0;;;2377:21:1;2434:2;2414:18;;;2407:30;2473:26;2453:18;;;2446:54;2517:18;;41159:71:0;;;;;;;;;42941:19:::1;::::0;::::1;42921:17;42941:19:::0;;;:12:::1;:19;::::0;;;;;;42974:14;;;42970:27:::1;;42990:7;42828:348:::0;;:::o;42970:27::-:1;43038:19;::::0;::::1;43060:1;43038:19:::0;;;:12:::1;:19;::::0;;;;:23;43071:45:::1;::::0;43095:9;43106;43071:23:::1;:45::i;:::-;43131:38;::::0;;2758:42:1;2827:15;;;2809:34;;2879:15;;2874:2;2859:18;;2852:43;2911:18;;;2904:34;;;43131:38:0::1;::::0;2736:2:1;2721:18;43131:38:0::1;;;;;;;42911:265;41240:1;42828:348:::0;;:::o;34694:136::-;34343:7;34369:12;;;;;;;;;;:22;;;32932:16;32943:4;32932:10;:16::i;:::-;34798:25:::1;34809:4;34815:7;34798:10;:25::i;:::-;;34694:136:::0;;;:::o;35796:245::-;35889:34;;;22980:10;35889:34;35885:102;;35946:30;;;;;;;;;;;;;;35885:102;35997:37;36009:4;36015:18;35997:11;:37::i;:::-;;35796:245;;:::o;42127:199::-;42222:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;42186:48;;;;;;42244:36;40398:26;42270:9;42244:10;:36::i;:::-;-1:-1:-1;42295:24:0;;3125:42:1;3113:55;;3095:74;;42295:24:0;;3083:2:1;3068:18;42295:24:0;;;;;;;;42127:199;:::o;41542:::-;41638:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41602:48;;;;;;41660:35;40261:25;41686:8;41660:11;:35::i;:::-;-1:-1:-1;41710:24:0;;3125:42:1;3113:55;;3095:74;;41710:24:0;;3083:2:1;3068:18;41710:24:0;2949:226:1;41747:181:0;41836:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41800:48;;;;;;41858:30;40329:23;41881:6;41858:10;:30::i;:::-;-1:-1:-1;41903:18:0;;3125:42:1;3113:55;;3095:74;;41903:18:0;;3083:2:1;3068:18;41903::0;2949:226:1;42543:279:0;41190:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41159:71;;;;;;;2395:2:1;41159:71:0;;;2377:21:1;2434:2;2414:18;;;2407:30;2473:26;2453:18;;;2446:54;2517:18;;41159:71:0;2193:348:1;41159:71:0;40513:6:::1;42631:10;:26;;42623:55;;;::::0;::::1;::::0;;3382:2:1;42623:55:0::1;::::0;::::1;3364:21:1::0;3421:2;3401:18;;;3394:30;3460:18;3440;;;3433:46;3496:18;;42623:55:0::1;3180:340:1::0;42623:55:0::1;42709:15;::::0;;42734:28;;;;42777:38:::1;::::0;;3699:25:1;;;3755:2;3740:18;;3733:34;;;42777:38:0::1;::::0;3672:18:1;42777:38:0::1;;;;;;;;42613:209;42543:279:::0;:::o;43182:253::-;41190:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41159:71;;;;;;;2395:2:1;41159:71:0;;;2377:21:1;2434:2;2414:18;;;2407:30;2473:26;2453:18;;;2446:54;2517:18;;41159:71:0;2193:348:1;41159:71:0;43296:14:::1;::::0;;43320:34;;;;43369:59:::1;::::0;;3699:25:1;;;3755:2;3740:18;;3733:34;;;43369:59:0::1;::::0;3672:18:1;43369:59:0::1;3525:248:1::0;41934:187:0;42026:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41990:48;;;;;;42048:31;40329:23;42072:6;42048:11;:31::i;:::-;-1:-1:-1;42094:20:0;;3125:42:1;3113:55;;3095:74;;42094:20:0;;3083:2:1;3068:18;42094:20:0;2949:226:1;35110:138:0;34343:7;34369:12;;;;;;;;;;:22;;;32932:16;32943:4;32932:10;:16::i;:::-;35215:26:::1;35227:4;35233:7;35215:11;:26::i;41343:193::-:0;41436:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41400:48;;;;;;41458:34;40261:25;41483:8;41458:10;:34::i;:::-;-1:-1:-1;41507:22:0;;3125:42:1;3113:55;;3095:74;;41507:22:0;;3083:2:1;3068:18;41507:22:0;2949:226:1;42332:205:0;42430:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;42394:48;;;;;;42452:37;40398:26;42479:9;42452:11;:37::i;:::-;-1:-1:-1;42504:26:0;;3125:42:1;3113:55;;3095:74;;42504:26:0;;3083:2:1;3068:18;42504:26:0;2949:226:1;37945:653:0;38120:4;38106:19;;;;38102:32;;37945:653;;;:::o;38102:32::-;38206:5;38215:1;38206:10;38202:23;;37945:653;;;:::o;38202:23::-;38238:20;;;;;38234:358;;38418:12;38435:2;:7;;38450:5;38435:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38417:43;;;38482:7;38474:39;;;;;;;4190:2:1;38474:39:0;;;4172:21:1;4229:2;4209:18;;;4202:30;4268:21;4248:18;;;4241:49;4307:18;;38474:39:0;3988:343:1;38234:358:0;38544:37;:26;;;38571:2;38575:5;38544:26;:37::i;33667:103::-;33733:30;33744:4;22980:10;33733;:30::i;:::-;33667:103;:::o;36647:316::-;36724:4;33422:12;;;;;;;;;;;:29;;;;;;;;;;;;;36740:217;;36783:6;:12;;;;;;;;;;;:29;;;;;;;;;;:36;;;;36815:4;36783:36;;;36865:12;22980:10;;22901:96;36865:12;36838:40;;36856:7;36838:40;;36850:4;36838:40;;;;;;;;;;-1:-1:-1;36899:4:0;36892:11;;36740:217;-1:-1:-1;36941:5:0;36934:12;;37198:317;37276:4;33422:12;;;;;;;;;;;:29;;;;;;;;;;;;;37292:217;;;37366:5;37334:12;;;;;;;;;;;:29;;;;;;;;;;;:37;;;;;;37390:40;22980:10;;37334:12;;37390:40;;37366:5;37390:40;-1:-1:-1;37451:4:0;37444:11;;26150:160;26259:43;;;26274:14;4528:55:1;;26259:43:0;;;4510:74:1;4600:18;;;;4593:34;;;26259:43:0;;;;;;;;;;4483:18:1;;;;26259:43:0;;;;;;;;;;;;;;26232:71;;26252:5;;26232:19;:71::i;33900:197::-;33399:4;33422:12;;;;;;;;;;;:29;;;;;;;;;;;;;33983:108;;34033:47;;;;;4540:42:1;4528:55;;34033:47:0;;;4510:74:1;4600:18;;;4593:34;;;4483:18;;34033:47:0;4336:297:1;28906:629:0;29325:23;29351:33;:27;;;29379:4;29351:27;:33::i;:::-;29325:59;;29398:10;:17;29419:1;29398:22;;:57;;;;;29436:10;29425:30;;;;;;;;;;;;:::i;:::-;29424:31;29398:57;29394:135;;;29478:40;;;;;3125:42:1;3113:55;;29478:40:0;;;3095:74:1;3068:18;;29478:40:0;2949:226:1;18686:151:0;18761:12;18792:38;18814:6;18822:4;18828:1;18792:21;:38::i;:::-;18785:45;18686:151;-1:-1:-1;;;18686:151:0:o;19161:392::-;19260:12;19312:5;19288:21;:29;19284:108;;;19340:41;;;;;19375:4;19340:41;;;3095:74:1;3068:18;;19340:41:0;2949:226:1;19284:108:0;19402:12;19416:23;19443:6;:11;;19462:5;19469:4;19443:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19401:73;;;;19491:55;19518:6;19526:7;19535:10;19491:26;:55::i;:::-;19484:62;19161:392;-1:-1:-1;;;;;;19161:392:0:o;20606:582::-;20750:12;20779:7;20774:408;;20802:19;20810:10;20802:7;:19::i;:::-;20774:408;;;21026:17;;:22;:49;;;;-1:-1:-1;21052:18:0;;;;:23;21026:49;21022:119;;;21102:24;;;;;3125:42:1;3113:55;;21102:24:0;;;3095:74:1;3068:18;;21102:24:0;2949:226:1;21022:119:0;-1:-1:-1;21161:10:0;21154:17;;21724:516;21855:17;;:21;21851:383;;22083:10;22077:17;22139:15;22126:10;22122:2;22118:19;22111:44;21851:383;22206:17;;;;;;;;;;;;;;14:332:1;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;180:9;167:23;230:66;223:5;219:78;212:5;209:89;199:117;;312:1;309;302:12;725:196;793:20;;853:42;842:54;;832:65;;822:93;;911:1;908;901:12;822:93;725:196;;;:::o;926:260::-;994:6;1002;1055:2;1043:9;1034:7;1030:23;1026:32;1023:52;;;1071:1;1068;1061:12;1023:52;1094:29;1113:9;1094:29;:::i;:::-;1084:39;;1142:38;1176:2;1165:9;1161:18;1142:38;:::i;:::-;1132:48;;926:260;;;;;:::o;1373:180::-;1432:6;1485:2;1473:9;1464:7;1460:23;1456:32;1453:52;;;1501:1;1498;1491:12;1453:52;-1:-1:-1;1524:23:1;;1373:180;-1:-1:-1;1373:180:1:o;1558:254::-;1626:6;1634;1687:2;1675:9;1666:7;1662:23;1658:32;1655:52;;;1703:1;1700;1693:12;1655:52;1739:9;1726:23;1716:33;;1768:38;1802:2;1791:9;1787:18;1768:38;:::i;1817:186::-;1876:6;1929:2;1917:9;1908:7;1904:23;1900:32;1897:52;;;1945:1;1942;1935:12;1897:52;1968:29;1987:9;1968:29;:::i;4940:277::-;5007:6;5060:2;5048:9;5039:7;5035:23;5031:32;5028:52;;;5076:1;5073;5066:12;5028:52;5108:9;5102:16;5161:5;5154:13;5147:21;5140:5;5137:32;5127:60;;5183:1;5180;5173:12;5222:412;5351:3;5389:6;5383:13;5414:1;5424:129;5438:6;5435:1;5432:13;5424:129;;;5536:4;5520:14;;;5516:25;;5510:32;5497:11;;;5490:53;5453:12;5424:129;;;-1:-1:-1;5608:1:1;5572:16;;5597:13;;;-1:-1:-1;5572:16:1;5222:412;-1:-1:-1;5222:412:1:o","abiDefinition":[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldChainGasAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"ChainGasAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFeeRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"FeeRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesSwept","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"governor","type":"address"}],"name":"GovernorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"governor","type":"address"}],"name":"GovernorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guard","type":"address"}],"name":"GuardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guard","type":"address"}],"name":"GuardRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_RATE_MAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GOVERNOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GUARD_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAYER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_governor","type":"address"}],"name":"addGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guard","type":"address"}],"name":"addGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_relayer","type":"address"}],"name":"addRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chainGasAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"protocolFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_governor","type":"address"}],"name":"removeGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guard","type":"address"}],"name":"removeGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_relayer","type":"address"}],"name":"removeRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"setChainGasAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"setProtocolFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"sweepProtocolFees","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"chainGasAmount()":{"notice":"Chain gas amount to forward as rebate if requested"},"protocolFeeRate()":{"notice":"Protocol fee rate taken on origin amount deposited in origin chain"},"protocolFees(address)":{"notice":"Protocol fee amounts accumulated"}},"version":1},"developerDoc":{"errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}],"AddressEmptyCode(address)":[{"details":"There's no code at `target` (it is not a contract)."}],"AddressInsufficientBalance(address)":[{"details":"The ETH balance of the account is not enough to perform the operation."}],"FailedInnerCall()":[{"details":"A call to an address target failed. The target may have reverted."}],"SafeERC20FailedOperation(address)":[{"details":"An operation with an ERC-20 token failed."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"addGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"addGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"addRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"removeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"removeGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"removeRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}],\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"AddressInsufficientBalance(address)\":[{\"details\":\"The ETH balance of the account is not enough to perform the operation.\"}],\"FailedInnerCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"chainGasAmount()\":{\"notice\":\"Chain gas amount to forward as rebate if requested\"},\"protocolFeeRate()\":{\"notice\":\"Protocol fee rate taken on origin amount deposited in origin chain\"},\"protocolFees(address)\":{\"notice\":\"Protocol fee amounts accumulated\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"Admin\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x5838f2ff3b1c4e6b40f973a29cce9f16871bd7a03add5aeeb7f876df39e92167\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://220c9bc7c31596b7d0ad7806037a3ebaed6c271c84df15e3789d850deef3fb1a\",\"dweb:/ipfs/QmU3xjtrAqz9fBLJKHC8Q4LCXpTi77i2oJJbu5Q5Ex2h4J\"]}},\"version\":1}"},"hashes":{"DEFAULT_ADMIN_ROLE()":"a217fddf","FEE_BPS()":"bf333f2c","FEE_RATE_MAX()":"0f5f6ed7","GOVERNOR_ROLE()":"ccc57490","GUARD_ROLE()":"03ed0ee5","RELAYER_ROLE()":"926d7d7f","addGovernor(address)":"3c4a25d0","addGuard(address)":"6913a63c","addRelayer(address)":"dd39f00d","chainGasAmount()":"e00a83e0","getRoleAdmin(bytes32)":"248a9ca3","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","protocolFeeRate()":"58f85880","protocolFees(address)":"dcf844a7","removeGovernor(address)":"eecdac88","removeGuard(address)":"b6235016","removeRelayer(address)":"60f0a5ac","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","setChainGasAmount(uint256)":"b250fe6b","setProtocolFeeRate(uint256)":"b13aa2d6","supportsInterface(bytes4)":"01ffc9a7","sweepProtocolFees(address,address)":"06f333f2"}},"solidity/FastBridge.sol:Context":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.","kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"details\":\"Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"Context\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x5838f2ff3b1c4e6b40f973a29cce9f16871bd7a03add5aeeb7f876df39e92167\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://220c9bc7c31596b7d0ad7806037a3ebaed6c271c84df15e3789d850deef3fb1a\",\"dweb:/ipfs/QmU3xjtrAqz9fBLJKHC8Q4LCXpTi77i2oJJbu5Q5Ex2h4J\"]}},\"version\":1}"},"hashes":{}},"solidity/FastBridge.sol:ERC165":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Implementation of the {IERC165} interface. Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check for the additional interface id that will be supported. For example: ```solidity function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); } ```","kind":"dev","methods":{"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Implementation of the {IERC165} interface. Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check for the additional interface id that will be supported. For example: ```solidity function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); } ```\",\"kind\":\"dev\",\"methods\":{\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"ERC165\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x5838f2ff3b1c4e6b40f973a29cce9f16871bd7a03add5aeeb7f876df39e92167\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://220c9bc7c31596b7d0ad7806037a3ebaed6c271c84df15e3789d850deef3fb1a\",\"dweb:/ipfs/QmU3xjtrAqz9fBLJKHC8Q4LCXpTi77i2oJJbu5Q5Ex2h4J\"]}},\"version\":1}"},"hashes":{"supportsInterface(bytes4)":"01ffc9a7"}},"solidity/FastBridge.sol:FastBridge":{"code":"0x60a06040523480156200001157600080fd5b5060405162003105380380620031058339810160408190526200003491620000fe565b80620000426000826200004f565b5050436080525062000130565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16620000f4576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620000ab3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001620000f8565b5060005b92915050565b6000602082840312156200011157600080fd5b81516001600160a01b03811681146200012957600080fd5b9392505050565b608051612fb96200014c600039600061067f0152612fb96000f3fe6080604052600436106102bb5760003560e01c806391d148541161016e578063b250fe6b116100cb578063d547741f1161007f578063dd39f00d11610064578063dd39f00d14610832578063e00a83e014610852578063eecdac881461086857600080fd5b8063d547741f146107e5578063dcf844a71461080557600080fd5b8063bf333f2c116100b0578063bf333f2c14610784578063ccc574901461079b578063d3cbc760146107cf57600080fd5b8063b250fe6b14610744578063b62350161461076457600080fd5b8063aa9641ab11610122578063add98c7011610107578063add98c70146106ee578063affed0e01461070e578063b13aa2d61461072457600080fd5b8063aa9641ab146106a1578063ac11fb1a146106c157600080fd5b8063a217fddf11610153578063a217fddf14610658578063a3ec191a1461066d578063a5bbe22b146104e557600080fd5b806391d14854146105e0578063926d7d7f1461062457600080fd5b8063458516941161021c578063820688d5116101d0578063886d36ff116101b5578063886d36ff1461052b5780638f0d6f171461054b57806391ad50391461055e57600080fd5b8063820688d5146104e55780638379a24f146104fb57600080fd5b80635eb7d946116102015780635eb7d9461461048557806360f0a5ac146104a55780636913a63c146104c557600080fd5b8063458516941461045c57806358f858801461046f57600080fd5b8063248a9ca31161027357806336568abe1161025857806336568abe146103fc5780633c4a25d01461041c57806341fcb6121461043c57600080fd5b8063248a9ca3146103ac5780632f2ff15d146103dc57600080fd5b8063051287bc116102a4578063051287bc1461033757806306f333f2146103745780630f5f6ed71461039657600080fd5b806301ffc9a7146102c057806303ed0ee5146102f5575b600080fd5b3480156102cc57600080fd5b506102e06102db366004612796565b610888565b60405190151581526020015b60405180910390f35b34801561030157600080fd5b506103297f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b6040519081526020016102ec565b34801561034357600080fd5b506103676103523660046127d8565b60046020526000908152604090205460ff1681565b6040516102ec9190612820565b34801561038057600080fd5b5061039461038f366004612886565b610921565b005b3480156103a257600080fd5b5061032961271081565b3480156103b857600080fd5b506103296103c73660046127d8565b60009081526020819052604090206001015490565b3480156103e857600080fd5b506103946103f73660046128bf565b610a59565b34801561040857600080fd5b506103946104173660046128bf565b610a84565b34801561042857600080fd5b506103946104373660046128e4565b610ad5565b34801561044857600080fd5b50610394610457366004612a29565b610b7b565b61039461046a366004612aa6565b610e23565b34801561047b57600080fd5b5061032960015481565b34801561049157600080fd5b506103946104a0366004612b49565b611131565b3480156104b157600080fd5b506103946104c03660046128e4565b611294565b3480156104d157600080fd5b506103946104e03660046128e4565b611333565b3480156104f157600080fd5b5061032961070881565b34801561050757600080fd5b506102e06105163660046127d8565b60066020526000908152604090205460ff1681565b34801561053757600080fd5b50610394610546366004612b86565b6113d2565b610394610559366004612b49565b6115ce565b34801561056a57600080fd5b506105b46105793660046127d8565b6005602052600090815260409020546bffffffffffffffffffffffff8116906c0100000000000000000000000090046001600160a01b031682565b604080516bffffffffffffffffffffffff90931683526001600160a01b039091166020830152016102ec565b3480156105ec57600080fd5b506102e06105fb3660046128bf565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561063057600080fd5b506103297fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b34801561066457600080fd5b50610329600081565b34801561067957600080fd5b506103297f000000000000000000000000000000000000000000000000000000000000000081565b3480156106ad57600080fd5b506102e06106bc3660046128bf565b611883565b3480156106cd57600080fd5b506106e16106dc366004612b49565b611988565b6040516102ec9190612bcb565b3480156106fa57600080fd5b506103946107093660046127d8565b6119fb565b34801561071a57600080fd5b5061032960075481565b34801561073057600080fd5b5061039461073f3660046127d8565b611bd3565b34801561075057600080fd5b5061039461075f3660046127d8565b611d1d565b34801561077057600080fd5b5061039461077f3660046128e4565b611df3565b34801561079057600080fd5b50610329620f424081565b3480156107a757600080fd5b506103297f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b3480156107db57600080fd5b50610329610e1081565b3480156107f157600080fd5b506103946108003660046128bf565b611e92565b34801561081157600080fd5b506103296108203660046128e4565b60026020526000908152604090205481565b34801561083e57600080fd5b5061039461084d3660046128e4565b611eb7565b34801561085e57600080fd5b5061032960035481565b34801561087457600080fd5b506103946108833660046128e4565b611f56565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061091b57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff166109be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064015b60405180910390fd5b6001600160a01b038216600090815260026020526040812054908190036109e457505050565b6001600160a01b038316600081815260026020526040812055610a08908383611ff5565b604080516001600160a01b038086168252841660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b5050565b600082815260208190526040902060010154610a7481612118565b610a7e8383612125565b50505050565b6001600160a01b0381163314610ac6576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ad082826121cf565b505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610b1057600080fd5b610b3a7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5582612125565b506040516001600160a01b03821681527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5906020015b60405180910390a150565b3360009081527ffaf93c3d007e112089dc8351e013e6685ef67703975d0224b26fc45941d4f1f5602052604090205460ff16610c13576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616c6c6572206973206e6f7420612072656c6179657200000000000000000060448201526064016109b5565b815160208301206000610c2584611988565b9050600260008381526004602081905260409091205460ff1690811115610c4e57610c4e6127f1565b14610c85576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040918290208251808401909352546bffffffffffffffffffffffff811683526c0100000000000000000000000090046001600160a01b03169082018190523314610d08576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611610d55576040517f1992d0bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600460205260409020805460ff1916600317905561010082015115610db15761010082015160808301516001600160a01b031660009081526002602052604081208054909190610dab908490612ce0565b90915550505b608082015160c0830151610dcf6001600160a01b0383168783611ff5565b604080516001600160a01b03848116825260208201849052881691339188917f582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac67891015b60405180910390a450505050505050565b46816000015163ffffffff1603610e66576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a08101511580610e79575060c0810151155b15610eb0576040517fe38820c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608101516001600160a01b03161580610ed5575060808101516001600160a01b0316155b15610f0c576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f1861070842612ce0565b8161010001511015610f56576040517f04b7fcc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610f6b3083606001518460a00151612252565b90506000806001541115610f9857620f424060015483610f8b9190612cf3565b610f959190612d0a565b90505b610fa28183612d45565b915060006040518061018001604052804663ffffffff168152602001856000015163ffffffff16815260200185602001516001600160a01b0316815260200185604001516001600160a01b0316815260200185606001516001600160a01b0316815260200185608001516001600160a01b031681526020018481526020018560c0015181526020018381526020018560e001511515815260200185610100015181526020016007600081548092919061105a90612d58565b9091555090526040516110709190602001612bcb565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152828252805160208083019190912060008181526004835293909320805460ff191660011790558701518751606089015160808a015160c08b015160e08c015195985095966001600160a01b039094169587957f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a95611122958b959094909390928e92612db4565b60405180910390a35050505050565b80516020820120600061114383611988565b9050610e108161014001516111589190612ce0565b4211611190576040517fe15ff9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008381526004602081905260409091205460ff16908111156111b7576111b76127f1565b146111ee576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600460208190526040909120805460ff191660018302179055506040810151608082015161010083015160c084015160009161122e91612ce0565b90506112446001600160a01b0383168483611ff5565b604080516001600160a01b0384811682526020820184905285169187917fb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958910160405180910390a3505050505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166112cf57600080fd5b6112f97fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4826121cf565b506040516001600160a01b03821681527f10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b90602001610b70565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661136e57600080fd5b6113987f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d82612125565b506040516001600160a01b03821681527f93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f5990602001610b70565b3360009081527ffaf93c3d007e112089dc8351e013e6685ef67703975d0224b26fc45941d4f1f5602052604090205460ff1661146a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616c6c6572206973206e6f7420612072656c6179657200000000000000000060448201526064016109b5565b81516020830120600061147c84611988565b9050610e108161014001516114919190612ce0565b4211156114ca576040517f559895a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008381526004602081905260409091205460ff16908111156114f1576114f16127f1565b14611528576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526004602090815260408083208054600260ff19909116179055805180820182526bffffffffffffffffffffffff4281168252338285018181528887526005865295849020925195516001600160a01b03166c0100000000000000000000000002959091169490941790555185815284917f4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4910160405180910390a350505050565b3360009081527ffaf93c3d007e112089dc8351e013e6685ef67703975d0224b26fc45941d4f1f5602052604090205460ff16611666576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616c6c6572206973206e6f7420612072656c6179657200000000000000000060448201526064016109b5565b80516020820120600061167883611988565b90504663ffffffff16816020015163ffffffff16146116c3576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806101400151421115611702576040517f559895a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205460ff161561174b576040517fbef7bb7d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660205260409020805460ff19166001179055606081015160a082015160e08301516003546101208501516117945750600061178e848484612252565b50611805565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b038416016117d85761178e84846117d38486612ce0565b612252565b6117e3848484612252565b506118038473eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee83612252565b505b845160808087015160a08089015160c0808b015160e08c01516040805163ffffffff90991689526001600160a01b0396871660208a0152938616938801939093526060870152938501528301849052861691339189917ff8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c9101610e12565b6000600260008481526004602081905260409091205460ff16908111156118ac576118ac6127f1565b146118e3576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600560209081526040918290208251808401909352546bffffffffffffffffffffffff811683526001600160a01b036c010000000000000000000000009091048116918301829052841614611969576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611949350505050565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201528251909161091b9184018101908401612e65565b3360009081527f92bf2f06c618f6add65571bf52eb90d22c9b52fd65028daa87260b82998b30bd602052604090205460ff16611a93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f43616c6c6572206973206e6f742061206775617264000000000000000000000060448201526064016109b5565b600260008281526004602081905260409091205460ff1690811115611aba57611aba6127f1565b14611af1576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600560209081526040918290208251808401909352546bffffffffffffffffffffffff8082168085526c010000000000000000000000009092046001600160a01b03169390920192909252610708914203161115611b80576040517f3e908aac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460209081526040808320805460ff19166001179055600590915280822082905551339183917f0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad49190a350565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16611c6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064016109b5565b612710811115611cd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064016109b5565b600180549082905560408051828152602081018490527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a15050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16611db5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064016109b5565b600380549082905560408051828152602081018490527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa9101611d11565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611e2e57600080fd5b611e587f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d826121cf565b506040516001600160a01b03821681527f59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d04890602001610b70565b600082815260208190526040902060010154611ead81612118565b610a7e83836121cf565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611ef257600080fd5b611f1c7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc482612125565b506040516001600160a01b03821681527f03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c590602001610b70565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611f9157600080fd5b611fbb7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55826121cf565b506040516001600160a01b03821681527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b90602001610b70565b306001600160a01b0383160361200a57505050565b8060000361201757505050565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03841601612104576000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612094576040519150601f19603f3d011682016040523d82523d6000602084013e612099565b606091505b5050905080610a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c65640000000000000000000000000060448201526064016109b5565b610ad06001600160a01b0384168383612422565b6121228133612496565b50565b6000828152602081815260408083206001600160a01b038516845290915281205460ff166121c7576000838152602081815260408083206001600160a01b03861684529091529020805460ff1916600117905561217f3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161091b565b50600061091b565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16156121c7576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161091b565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146123bb5761228a836001600160a01b0316612502565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528416906370a0823190602401602060405180830381865afa1580156122e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061230d9190612f31565b90506123246001600160a01b0384163386856125a8565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528291908516906370a0823190602401602060405180830381865afa158015612386573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123aa9190612f31565b6123b49190612d45565b905061241b565b3482146123f4576040517f81de0bf300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0384163014612418576124186001600160a01b0384168584611ff5565b50345b9392505050565b6040516001600160a01b03838116602483015260448201839052610ad091859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506125e1565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610a55576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602481018390526044016109b5565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03821601612564576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03163b600003612122576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038481166024830152838116604483015260648201839052610a7e9186918216906323b872dd9060840161244f565b60006125f66001600160a01b0384168361265d565b9050805160001415801561261b5750808060200190518101906126199190612f4a565b155b15610ad0576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024016109b5565b606061241b8383600084600080856001600160a01b031684866040516126839190612f67565b60006040518083038185875af1925050503d80600081146126c0576040519150601f19603f3d011682016040523d82523d6000602084013e6126c5565b606091505b50915091506126d58683836126df565b9695505050505050565b6060826126f4576126ef82612754565b61241b565b815115801561270b57506001600160a01b0384163b155b1561274d576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016109b5565b508061241b565b8051156127645780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602082840312156127a857600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461241b57600080fd5b6000602082840312156127ea57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016005831061285b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6001600160a01b038116811461212257600080fd5b803561288181612861565b919050565b6000806040838503121561289957600080fd5b82356128a481612861565b915060208301356128b481612861565b809150509250929050565b600080604083850312156128d257600080fd5b8235915060208301356128b481612861565b6000602082840312156128f657600080fd5b813561241b81612861565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171561295457612954612901565b60405290565b604051610180810167ffffffffffffffff8111828210171561295457612954612901565b600082601f83011261298f57600080fd5b813567ffffffffffffffff808211156129aa576129aa612901565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156129f0576129f0612901565b81604052838152866020858801011115612a0957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215612a3c57600080fd5b823567ffffffffffffffff811115612a5357600080fd5b612a5f8582860161297e565b92505060208301356128b481612861565b63ffffffff8116811461212257600080fd5b803561288181612a70565b801515811461212257600080fd5b803561288181612a8d565b60006101208284031215612ab957600080fd5b612ac1612930565b612aca83612a82565b8152612ad860208401612876565b6020820152612ae960408401612876565b6040820152612afa60608401612876565b6060820152612b0b60808401612876565b608082015260a083013560a082015260c083013560c0820152612b3060e08401612a9b565b60e0820152610100928301359281019290925250919050565b600060208284031215612b5b57600080fd5b813567ffffffffffffffff811115612b7257600080fd5b612b7e8482850161297e565b949350505050565b60008060408385031215612b9957600080fd5b823567ffffffffffffffff811115612bb057600080fd5b612bbc8582860161297e565b95602094909401359450505050565b815163ffffffff16815261018081016020830151612bf1602084018263ffffffff169052565b506040830151612c0c60408401826001600160a01b03169052565b506060830151612c2760608401826001600160a01b03169052565b506080830151612c4260808401826001600160a01b03169052565b5060a0830151612c5d60a08401826001600160a01b03169052565b5060c083015160c083015260e083015160e083015261010080840151818401525061012080840151612c928285018215159052565b5050610140838101519083015261016092830151929091019190915290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561091b5761091b612cb1565b808202811582820484141761091b5761091b612cb1565b600082612d40577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561091b5761091b612cb1565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612d8957612d89612cb1565b5060010190565b60005b83811015612dab578181015183820152602001612d93565b50506000910152565b60e08152600088518060e0840152610100612dd58282860160208e01612d90565b63ffffffff9990991660208401526001600160a01b039788166040840152959096166060820152608081019390935260a0830191909152151560c0820152601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190910192915050565b805161288181612a70565b805161288181612861565b805161288181612a8d565b60006101808284031215612e7857600080fd5b612e8061295a565b612e8983612e44565b8152612e9760208401612e44565b6020820152612ea860408401612e4f565b6040820152612eb960608401612e4f565b6060820152612eca60808401612e4f565b6080820152612edb60a08401612e4f565b60a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120612f0e818501612e5a565b908201526101408381015190820152610160928301519281019290925250919050565b600060208284031215612f4357600080fd5b5051919050565b600060208284031215612f5c57600080fd5b815161241b81612a8d565b60008251612f79818460208701612d90565b919091019291505056fea2646970667358221220cfbaf6e83822ac30c6a2a632f0f3210ee79769ee0c58ec096e96669f3b90e1c064736f6c63430008140033","runtime-code":"0x6080604052600436106102bb5760003560e01c806391d148541161016e578063b250fe6b116100cb578063d547741f1161007f578063dd39f00d11610064578063dd39f00d14610832578063e00a83e014610852578063eecdac881461086857600080fd5b8063d547741f146107e5578063dcf844a71461080557600080fd5b8063bf333f2c116100b0578063bf333f2c14610784578063ccc574901461079b578063d3cbc760146107cf57600080fd5b8063b250fe6b14610744578063b62350161461076457600080fd5b8063aa9641ab11610122578063add98c7011610107578063add98c70146106ee578063affed0e01461070e578063b13aa2d61461072457600080fd5b8063aa9641ab146106a1578063ac11fb1a146106c157600080fd5b8063a217fddf11610153578063a217fddf14610658578063a3ec191a1461066d578063a5bbe22b146104e557600080fd5b806391d14854146105e0578063926d7d7f1461062457600080fd5b8063458516941161021c578063820688d5116101d0578063886d36ff116101b5578063886d36ff1461052b5780638f0d6f171461054b57806391ad50391461055e57600080fd5b8063820688d5146104e55780638379a24f146104fb57600080fd5b80635eb7d946116102015780635eb7d9461461048557806360f0a5ac146104a55780636913a63c146104c557600080fd5b8063458516941461045c57806358f858801461046f57600080fd5b8063248a9ca31161027357806336568abe1161025857806336568abe146103fc5780633c4a25d01461041c57806341fcb6121461043c57600080fd5b8063248a9ca3146103ac5780632f2ff15d146103dc57600080fd5b8063051287bc116102a4578063051287bc1461033757806306f333f2146103745780630f5f6ed71461039657600080fd5b806301ffc9a7146102c057806303ed0ee5146102f5575b600080fd5b3480156102cc57600080fd5b506102e06102db366004612796565b610888565b60405190151581526020015b60405180910390f35b34801561030157600080fd5b506103297f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b6040519081526020016102ec565b34801561034357600080fd5b506103676103523660046127d8565b60046020526000908152604090205460ff1681565b6040516102ec9190612820565b34801561038057600080fd5b5061039461038f366004612886565b610921565b005b3480156103a257600080fd5b5061032961271081565b3480156103b857600080fd5b506103296103c73660046127d8565b60009081526020819052604090206001015490565b3480156103e857600080fd5b506103946103f73660046128bf565b610a59565b34801561040857600080fd5b506103946104173660046128bf565b610a84565b34801561042857600080fd5b506103946104373660046128e4565b610ad5565b34801561044857600080fd5b50610394610457366004612a29565b610b7b565b61039461046a366004612aa6565b610e23565b34801561047b57600080fd5b5061032960015481565b34801561049157600080fd5b506103946104a0366004612b49565b611131565b3480156104b157600080fd5b506103946104c03660046128e4565b611294565b3480156104d157600080fd5b506103946104e03660046128e4565b611333565b3480156104f157600080fd5b5061032961070881565b34801561050757600080fd5b506102e06105163660046127d8565b60066020526000908152604090205460ff1681565b34801561053757600080fd5b50610394610546366004612b86565b6113d2565b610394610559366004612b49565b6115ce565b34801561056a57600080fd5b506105b46105793660046127d8565b6005602052600090815260409020546bffffffffffffffffffffffff8116906c0100000000000000000000000090046001600160a01b031682565b604080516bffffffffffffffffffffffff90931683526001600160a01b039091166020830152016102ec565b3480156105ec57600080fd5b506102e06105fb3660046128bf565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561063057600080fd5b506103297fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b34801561066457600080fd5b50610329600081565b34801561067957600080fd5b506103297f000000000000000000000000000000000000000000000000000000000000000081565b3480156106ad57600080fd5b506102e06106bc3660046128bf565b611883565b3480156106cd57600080fd5b506106e16106dc366004612b49565b611988565b6040516102ec9190612bcb565b3480156106fa57600080fd5b506103946107093660046127d8565b6119fb565b34801561071a57600080fd5b5061032960075481565b34801561073057600080fd5b5061039461073f3660046127d8565b611bd3565b34801561075057600080fd5b5061039461075f3660046127d8565b611d1d565b34801561077057600080fd5b5061039461077f3660046128e4565b611df3565b34801561079057600080fd5b50610329620f424081565b3480156107a757600080fd5b506103297f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b3480156107db57600080fd5b50610329610e1081565b3480156107f157600080fd5b506103946108003660046128bf565b611e92565b34801561081157600080fd5b506103296108203660046128e4565b60026020526000908152604090205481565b34801561083e57600080fd5b5061039461084d3660046128e4565b611eb7565b34801561085e57600080fd5b5061032960035481565b34801561087457600080fd5b506103946108833660046128e4565b611f56565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061091b57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff166109be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064015b60405180910390fd5b6001600160a01b038216600090815260026020526040812054908190036109e457505050565b6001600160a01b038316600081815260026020526040812055610a08908383611ff5565b604080516001600160a01b038086168252841660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b5050565b600082815260208190526040902060010154610a7481612118565b610a7e8383612125565b50505050565b6001600160a01b0381163314610ac6576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ad082826121cf565b505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610b1057600080fd5b610b3a7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5582612125565b506040516001600160a01b03821681527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5906020015b60405180910390a150565b3360009081527ffaf93c3d007e112089dc8351e013e6685ef67703975d0224b26fc45941d4f1f5602052604090205460ff16610c13576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616c6c6572206973206e6f7420612072656c6179657200000000000000000060448201526064016109b5565b815160208301206000610c2584611988565b9050600260008381526004602081905260409091205460ff1690811115610c4e57610c4e6127f1565b14610c85576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040918290208251808401909352546bffffffffffffffffffffffff811683526c0100000000000000000000000090046001600160a01b03169082018190523314610d08576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611610d55576040517f1992d0bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600460205260409020805460ff1916600317905561010082015115610db15761010082015160808301516001600160a01b031660009081526002602052604081208054909190610dab908490612ce0565b90915550505b608082015160c0830151610dcf6001600160a01b0383168783611ff5565b604080516001600160a01b03848116825260208201849052881691339188917f582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac67891015b60405180910390a450505050505050565b46816000015163ffffffff1603610e66576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a08101511580610e79575060c0810151155b15610eb0576040517fe38820c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608101516001600160a01b03161580610ed5575060808101516001600160a01b0316155b15610f0c576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f1861070842612ce0565b8161010001511015610f56576040517f04b7fcc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610f6b3083606001518460a00151612252565b90506000806001541115610f9857620f424060015483610f8b9190612cf3565b610f959190612d0a565b90505b610fa28183612d45565b915060006040518061018001604052804663ffffffff168152602001856000015163ffffffff16815260200185602001516001600160a01b0316815260200185604001516001600160a01b0316815260200185606001516001600160a01b0316815260200185608001516001600160a01b031681526020018481526020018560c0015181526020018381526020018560e001511515815260200185610100015181526020016007600081548092919061105a90612d58565b9091555090526040516110709190602001612bcb565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152828252805160208083019190912060008181526004835293909320805460ff191660011790558701518751606089015160808a015160c08b015160e08c015195985095966001600160a01b039094169587957f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a95611122958b959094909390928e92612db4565b60405180910390a35050505050565b80516020820120600061114383611988565b9050610e108161014001516111589190612ce0565b4211611190576040517fe15ff9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008381526004602081905260409091205460ff16908111156111b7576111b76127f1565b146111ee576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600460208190526040909120805460ff191660018302179055506040810151608082015161010083015160c084015160009161122e91612ce0565b90506112446001600160a01b0383168483611ff5565b604080516001600160a01b0384811682526020820184905285169187917fb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958910160405180910390a3505050505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166112cf57600080fd5b6112f97fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4826121cf565b506040516001600160a01b03821681527f10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b90602001610b70565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661136e57600080fd5b6113987f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d82612125565b506040516001600160a01b03821681527f93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f5990602001610b70565b3360009081527ffaf93c3d007e112089dc8351e013e6685ef67703975d0224b26fc45941d4f1f5602052604090205460ff1661146a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616c6c6572206973206e6f7420612072656c6179657200000000000000000060448201526064016109b5565b81516020830120600061147c84611988565b9050610e108161014001516114919190612ce0565b4211156114ca576040517f559895a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008381526004602081905260409091205460ff16908111156114f1576114f16127f1565b14611528576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526004602090815260408083208054600260ff19909116179055805180820182526bffffffffffffffffffffffff4281168252338285018181528887526005865295849020925195516001600160a01b03166c0100000000000000000000000002959091169490941790555185815284917f4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4910160405180910390a350505050565b3360009081527ffaf93c3d007e112089dc8351e013e6685ef67703975d0224b26fc45941d4f1f5602052604090205460ff16611666576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616c6c6572206973206e6f7420612072656c6179657200000000000000000060448201526064016109b5565b80516020820120600061167883611988565b90504663ffffffff16816020015163ffffffff16146116c3576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806101400151421115611702576040517f559895a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205460ff161561174b576040517fbef7bb7d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660205260409020805460ff19166001179055606081015160a082015160e08301516003546101208501516117945750600061178e848484612252565b50611805565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b038416016117d85761178e84846117d38486612ce0565b612252565b6117e3848484612252565b506118038473eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee83612252565b505b845160808087015160a08089015160c0808b015160e08c01516040805163ffffffff90991689526001600160a01b0396871660208a0152938616938801939093526060870152938501528301849052861691339189917ff8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c9101610e12565b6000600260008481526004602081905260409091205460ff16908111156118ac576118ac6127f1565b146118e3576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600560209081526040918290208251808401909352546bffffffffffffffffffffffff811683526001600160a01b036c010000000000000000000000009091048116918301829052841614611969576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611949350505050565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201528251909161091b9184018101908401612e65565b3360009081527f92bf2f06c618f6add65571bf52eb90d22c9b52fd65028daa87260b82998b30bd602052604090205460ff16611a93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f43616c6c6572206973206e6f742061206775617264000000000000000000000060448201526064016109b5565b600260008281526004602081905260409091205460ff1690811115611aba57611aba6127f1565b14611af1576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600560209081526040918290208251808401909352546bffffffffffffffffffffffff8082168085526c010000000000000000000000009092046001600160a01b03169390920192909252610708914203161115611b80576040517f3e908aac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460209081526040808320805460ff19166001179055600590915280822082905551339183917f0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad49190a350565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16611c6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064016109b5565b612710811115611cd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064016109b5565b600180549082905560408051828152602081018490527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a15050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16611db5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064016109b5565b600380549082905560408051828152602081018490527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa9101611d11565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611e2e57600080fd5b611e587f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d826121cf565b506040516001600160a01b03821681527f59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d04890602001610b70565b600082815260208190526040902060010154611ead81612118565b610a7e83836121cf565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611ef257600080fd5b611f1c7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc482612125565b506040516001600160a01b03821681527f03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c590602001610b70565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611f9157600080fd5b611fbb7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55826121cf565b506040516001600160a01b03821681527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b90602001610b70565b306001600160a01b0383160361200a57505050565b8060000361201757505050565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03841601612104576000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612094576040519150601f19603f3d011682016040523d82523d6000602084013e612099565b606091505b5050905080610a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c65640000000000000000000000000060448201526064016109b5565b610ad06001600160a01b0384168383612422565b6121228133612496565b50565b6000828152602081815260408083206001600160a01b038516845290915281205460ff166121c7576000838152602081815260408083206001600160a01b03861684529091529020805460ff1916600117905561217f3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161091b565b50600061091b565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16156121c7576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161091b565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146123bb5761228a836001600160a01b0316612502565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528416906370a0823190602401602060405180830381865afa1580156122e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061230d9190612f31565b90506123246001600160a01b0384163386856125a8565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528291908516906370a0823190602401602060405180830381865afa158015612386573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123aa9190612f31565b6123b49190612d45565b905061241b565b3482146123f4576040517f81de0bf300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0384163014612418576124186001600160a01b0384168584611ff5565b50345b9392505050565b6040516001600160a01b03838116602483015260448201839052610ad091859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506125e1565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610a55576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602481018390526044016109b5565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03821601612564576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03163b600003612122576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038481166024830152838116604483015260648201839052610a7e9186918216906323b872dd9060840161244f565b60006125f66001600160a01b0384168361265d565b9050805160001415801561261b5750808060200190518101906126199190612f4a565b155b15610ad0576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024016109b5565b606061241b8383600084600080856001600160a01b031684866040516126839190612f67565b60006040518083038185875af1925050503d80600081146126c0576040519150601f19603f3d011682016040523d82523d6000602084013e6126c5565b606091505b50915091506126d58683836126df565b9695505050505050565b6060826126f4576126ef82612754565b61241b565b815115801561270b57506001600160a01b0384163b155b1561274d576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016109b5565b508061241b565b8051156127645780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602082840312156127a857600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461241b57600080fd5b6000602082840312156127ea57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016005831061285b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6001600160a01b038116811461212257600080fd5b803561288181612861565b919050565b6000806040838503121561289957600080fd5b82356128a481612861565b915060208301356128b481612861565b809150509250929050565b600080604083850312156128d257600080fd5b8235915060208301356128b481612861565b6000602082840312156128f657600080fd5b813561241b81612861565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171561295457612954612901565b60405290565b604051610180810167ffffffffffffffff8111828210171561295457612954612901565b600082601f83011261298f57600080fd5b813567ffffffffffffffff808211156129aa576129aa612901565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156129f0576129f0612901565b81604052838152866020858801011115612a0957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215612a3c57600080fd5b823567ffffffffffffffff811115612a5357600080fd5b612a5f8582860161297e565b92505060208301356128b481612861565b63ffffffff8116811461212257600080fd5b803561288181612a70565b801515811461212257600080fd5b803561288181612a8d565b60006101208284031215612ab957600080fd5b612ac1612930565b612aca83612a82565b8152612ad860208401612876565b6020820152612ae960408401612876565b6040820152612afa60608401612876565b6060820152612b0b60808401612876565b608082015260a083013560a082015260c083013560c0820152612b3060e08401612a9b565b60e0820152610100928301359281019290925250919050565b600060208284031215612b5b57600080fd5b813567ffffffffffffffff811115612b7257600080fd5b612b7e8482850161297e565b949350505050565b60008060408385031215612b9957600080fd5b823567ffffffffffffffff811115612bb057600080fd5b612bbc8582860161297e565b95602094909401359450505050565b815163ffffffff16815261018081016020830151612bf1602084018263ffffffff169052565b506040830151612c0c60408401826001600160a01b03169052565b506060830151612c2760608401826001600160a01b03169052565b506080830151612c4260808401826001600160a01b03169052565b5060a0830151612c5d60a08401826001600160a01b03169052565b5060c083015160c083015260e083015160e083015261010080840151818401525061012080840151612c928285018215159052565b5050610140838101519083015261016092830151929091019190915290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561091b5761091b612cb1565b808202811582820484141761091b5761091b612cb1565b600082612d40577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561091b5761091b612cb1565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612d8957612d89612cb1565b5060010190565b60005b83811015612dab578181015183820152602001612d93565b50506000910152565b60e08152600088518060e0840152610100612dd58282860160208e01612d90565b63ffffffff9990991660208401526001600160a01b039788166040840152959096166060820152608081019390935260a0830191909152151560c0820152601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190910192915050565b805161288181612a70565b805161288181612861565b805161288181612a8d565b60006101808284031215612e7857600080fd5b612e8061295a565b612e8983612e44565b8152612e9760208401612e44565b6020820152612ea860408401612e4f565b6040820152612eb960608401612e4f565b6060820152612eca60808401612e4f565b6080820152612edb60a08401612e4f565b60a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120612f0e818501612e5a565b908201526101408381015190820152610160928301519281019290925250919050565b600060208284031215612f4357600080fd5b5051919050565b600060208284031215612f5c57600080fd5b815161241b81612a8d565b60008251612f79818460208701612d90565b919091019291505056fea2646970667358221220cfbaf6e83822ac30c6a2a632f0f3210ee79769ee0c58ec096e96669f3b90e1c064736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"43468:11252:0:-:0;;;44636:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;44670:6;41292:38;32700:4;44670:6;41292:10;:38::i;:::-;-1:-1:-1;;44702:12:0::1;44688:26;::::0;-1:-1:-1;43468:11252:0;;36647:316;36724:4;33422:12;;;;;;;;;;;-1:-1:-1;;;;;33422:29:0;;;;;;;;;;;;36740:217;;36783:6;:12;;;;;;;;;;;-1:-1:-1;;;;;36783:29:0;;;;;;;;;:36;;-1:-1:-1;;36783:36:0;36815:4;36783:36;;;36865:12;22980:10;;22901:96;36865:12;-1:-1:-1;;;;;36838:40:0;36856:7;-1:-1:-1;;;;;36838:40:0;36850:4;36838:40;;;;;;;;;;-1:-1:-1;36899:4:0;36892:11;;36740:217;-1:-1:-1;36941:5:0;36740:217;36647:316;;;;:::o;14:290:1:-;84:6;137:2;125:9;116:7;112:23;108:32;105:52;;;153:1;150;143:12;105:52;179:16;;-1:-1:-1;;;;;224:31:1;;214:42;;204:70;;270:1;267;260:12;204:70;293:5;14:290;-1:-1:-1;;;14:290:1:o;:::-;43468:11252:0;;;;;;;;;;;;","srcMapRuntime":"43468:11252:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33033:202;;;;;;;;;;-1:-1:-1;33033:202:0;;;;;:::i;:::-;;:::i;:::-;;;612:14:1;;605:22;587:41;;575:2;560:18;33033:202:0;;;;;;;;40292:60;;;;;;;;;;;;40329:23;40292:60;;;;;785:25:1;;;773:2;758:18;40292:60:0;639:177:1;44188:54:0;;;;;;;;;;-1:-1:-1;44188:54:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;42828:348::-;;;;;;;;;;-1:-1:-1;42828:348:0;;;;;:::i;:::-;;:::i;:::-;;40474:45;;;;;;;;;;;;40513:6;40474:45;;34278:120;;;;;;;;;;-1:-1:-1;34278:120:0;;;;;:::i;:::-;34343:7;34369:12;;;;;;;;;;:22;;;;34278:120;34694:136;;;;;;;;;;-1:-1:-1;34694:136:0;;;;;:::i;:::-;;:::i;35796:245::-;;;;;;;;;;-1:-1:-1;35796:245:0;;;;;:::i;:::-;;:::i;42127:199::-;;;;;;;;;;-1:-1:-1;42127:199:0;;;;;:::i;:::-;;:::i;52078:1135::-;;;;;;;;;;-1:-1:-1;52078:1135:0;;;;;:::i;:::-;;:::i;46321:2114::-;;;;;;:::i;:::-;;:::i;40636:30::-;;;;;;;;;;;;;;;;53803:915;;;;;;;;;;-1:-1:-1;53803:915:0;;;;;:::i;:::-;;:::i;41542:199::-;;;;;;;;;;-1:-1:-1;41542:199:0;;;;;:::i;:::-;;:::i;41747:181::-;;;;;;;;;;-1:-1:-1;41747:181:0;;;;;:::i;:::-;;:::i;43918:56::-;;;;;;;;;;;;43964:10;43918:56;;44433:44;;;;;;;;;;-1:-1:-1;44433:44:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;50218:793;;;;;;;;;;-1:-1:-1;50218:793:0;;;;;:::i;:::-;;:::i;48473:1707::-;;;;;;:::i;:::-;;:::i;44307:51::-;;;;;;;;;;-1:-1:-1;44307:51:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;44307:51:0;;;;;;;7428:26:1;7416:39;;;7398:58;;-1:-1:-1;;;;;7492:55:1;;;7487:2;7472:18;;7465:83;7371:18;44307:51:0;7226:328:1;33322:136:0;;;;;;;;;;-1:-1:-1;33322:136:0;;;;;:::i;:::-;33399:4;33422:12;;;;;;;;;;;-1:-1:-1;;;;;33422:29:0;;;;;;;;;;;;;;;33322:136;40222:64;;;;;;;;;;;;40261:25;40222:64;;32655:49;;;;;;;;;;-1:-1:-1;32655:49:0;32700:4;32655:49;;44593:36;;;;;;;;;;;;;;;51667:373;;;;;;;;;;-1:-1:-1;51667:373:0;;;;;:::i;:::-;;:::i;46120:163::-;;;;;;;;;;-1:-1:-1;46120:163:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;53251:514::-;;;;;;;;;;-1:-1:-1;53251:514:0;;;;;:::i;:::-;;:::i;44516:20::-;;;;;;;;;;;;;;;;42543:279;;;;;;;;;;-1:-1:-1;42543:279:0;;;;;:::i;:::-;;:::i;43182:253::-;;;;;;;;;;-1:-1:-1;43182:253:0;;;;;:::i;:::-;;:::i;41934:187::-;;;;;;;;;;-1:-1:-1;41934:187:0;;;;;:::i;:::-;;:::i;40431:37::-;;;;;;;;;;;;40465:3;40431:37;;40358:66;;;;;;;;;;;;40398:26;40358:66;;43782:49;;;;;;;;;;;;43821:10;43782:49;;35110:138;;;;;;;;;;-1:-1:-1;35110:138:0;;;;;:::i;:::-;;:::i;40722:47::-;;;;;;;;;;-1:-1:-1;40722:47:0;;;;;:::i;:::-;;;;;;;;;;;;;;41343:193;;;;;;;;;;-1:-1:-1;41343:193:0;;;;;:::i;:::-;;:::i;40843:29::-;;;;;;;;;;;;;;;;42332:205;;;;;;;;;;-1:-1:-1;42332:205:0;;;;;:::i;:::-;;:::i;33033:202::-;33118:4;33141:47;;;33156:32;33141:47;;:87;;-1:-1:-1;24946:25:0;24931:40;;;;33192:36;33134:94;33033:202;-1:-1:-1;;33033:202:0:o;42828:348::-;41190:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41159:71;;;;;;;9425:2:1;41159:71:0;;;9407:21:1;9464:2;9444:18;;;9437:30;9503:26;9483:18;;;9476:54;9547:18;;41159:71:0;;;;;;;;;-1:-1:-1;;;;;42941:19:0;::::1;42921:17;42941:19:::0;;;:12:::1;:19;::::0;;;;;;42974:14;;;42970:27:::1;;42990:7;42828:348:::0;;:::o;42970:27::-:1;-1:-1:-1::0;;;;;43038:19:0;::::1;43060:1;43038:19:::0;;;:12:::1;:19;::::0;;;;:23;43071:45:::1;::::0;43095:9;43106;43071:23:::1;:45::i;:::-;43131:38;::::0;;-1:-1:-1;;;;;9857:15:1;;;9839:34;;9909:15;;9904:2;9889:18;;9882:43;9941:18;;;9934:34;;;43131:38:0::1;::::0;9766:2:1;9751:18;43131:38:0::1;;;;;;;42911:265;41240:1;42828:348:::0;;:::o;34694:136::-;34343:7;34369:12;;;;;;;;;;:22;;;32932:16;32943:4;32932:10;:16::i;:::-;34798:25:::1;34809:4;34815:7;34798:10;:25::i;:::-;;34694:136:::0;;;:::o;35796:245::-;-1:-1:-1;;;;;35889:34:0;;22980:10;35889:34;35885:102;;35946:30;;;;;;;;;;;;;;35885:102;35997:37;36009:4;36015:18;35997:11;:37::i;:::-;;35796:245;;:::o;42127:199::-;42222:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;42186:48;;;;;;42244:36;40398:26;42270:9;42244:10;:36::i;:::-;-1:-1:-1;42295:24:0;;-1:-1:-1;;;;;10143:55:1;;10125:74;;42295:24:0;;10113:2:1;10098:18;42295:24:0;;;;;;;;42127:199;:::o;52078:1135::-;41062:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41032:69;;;;;;;10412:2:1;41032:69:0;;;10394:21:1;10451:2;10431:18;;;10424:30;10490:25;10470:18;;;10463:53;10533:18;;41032:69:0;10210:347:1;41032:69:0;52182:18;;::::1;::::0;::::1;::::0;52158:21:::1;52249:29;52192:7:::0;52249:20:::1;:29::i;:::-;52210:68:::0;-1:-1:-1;52396:27:0::1;52363:29;::::0;;;:14:::1;:29;::::0;;;;;;;;::::1;;::::0;:60;::::1;;;;;;:::i;:::-;;52359:90;;52432:17;;;;;;;;;;;;;;52359:90;52460:24;52487:27:::0;;;:12:::1;:27;::::0;;;;;;;;52460:54;;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;;;;::::1;-1:-1:-1::0;;;;;52460:54:0::1;::::0;;::::1;::::0;;;52545:10:::1;52528:27;52524:57;;52564:17;;;;;;;;;;;;;;52524:57;51597:15:::0;;43687:10:::1;::::0;51578:15;51571:41;51563:49;;52595:35:::1;52591:72;;52639:24;;;;;;;;;;;;;;52591:72;52674:29;::::0;;;:14:::1;:29;::::0;;;;:60;;-1:-1:-1;;52674:60:0::1;52706:28;52674:60;::::0;;52809:27:::1;::::0;::::1;::::0;:31;52805:105:::1;;52883:27;::::0;::::1;::::0;52855:23:::1;::::0;::::1;::::0;-1:-1:-1;;;;;52842:37:0::1;;::::0;;;:12:::1;:37;::::0;;;;:68;;:37;;;:68:::1;::::0;52883:27;;52842:68:::1;:::i;:::-;::::0;;;-1:-1:-1;;52805:105:0::1;53005:23;::::0;::::1;::::0;53055:24:::1;::::0;::::1;::::0;53089:35:::1;-1:-1:-1::0;;;;;53089:23:0;::::1;53113:2:::0;53055:24;53089:23:::1;:35::i;:::-;53140:66;::::0;;-1:-1:-1;;;;;11073:55:1;;;11055:74;;11160:2;11145:18;;11138:34;;;53140:66:0;::::1;::::0;53176:10:::1;::::0;53161:13;;53140:66:::1;::::0;11028:18:1;53140:66:0::1;;;;;;;;52148:1065;;;;;52078:1135:::0;;:::o;46321:2114::-;46448:13;46427:6;:17;;;:34;;;46423:63;;46470:16;;;;;;;;;;;;;;46423:63;46500:19;;;;:24;;:50;;-1:-1:-1;46528:17:0;;;;:22;46500:50;46496:80;;;46559:17;;;;;;;;;;;;;;46496:80;46590:18;;;;-1:-1:-1;;;;;46590:32:0;;;:66;;-1:-1:-1;46626:16:0;;;;-1:-1:-1;;;;;46626:30:0;;46590:66;46586:92;;;46665:13;;;;;;;;;;;;;;46586:92;46710:37;43964:10;46710:15;:37;:::i;:::-;46692:6;:15;;;:55;46688:86;;;46756:18;;;;;;;;;;;;;;46688:86;46909:20;46932:66;46951:4;46958:6;:18;;;46978:6;:19;;;46932:10;:66::i;:::-;46909:89;;47066:23;47121:1;47103:15;;:19;47099:85;;;40465:3;47158:15;;47143:12;:30;;;;:::i;:::-;47142:42;;;;:::i;:::-;47124:60;;47099:85;47194:31;47210:15;47194:31;;:::i;:::-;;;47338:20;47385:618;;;;;;;;47443:13;47385:618;;;;;;47488:6;:17;;;47385:618;;;;;;47537:6;:13;;;-1:-1:-1;;;;;47385:618:0;;;;;47583:6;:9;;;-1:-1:-1;;;;;47385:618:0;;;;;47623:6;:18;;;-1:-1:-1;;;;;47385:618:0;;;;;47670:6;:16;;;-1:-1:-1;;;;;47385:618:0;;;;;47718:12;47385:618;;;;47760:6;:17;;;47385:618;;;;47812:15;47385:618;;;;47859:6;:19;;;47385:618;;;;;;47906:6;:15;;;47385:618;;;;47946:5;;:7;;;;;;;;;:::i;:::-;;;;-1:-1:-1;47385:618:0;;47361:652;;;;;;;;:::i;:::-;;;;;;;;;;;;;;48047:18;;47361:652;48047:18;;;;;;;48023:21;48075:29;;;:14;:29;;;;;;:54;;-1:-1:-1;;48075:54:0;48107:22;48075:54;;;48201:13;;;48249:17;;48280:18;;;;48312:16;;;;48368:17;;;;48399:19;;;;47361:652;;-1:-1:-1;48047:18:0;;-1:-1:-1;;;;;48145:283:0;;;;48047:18;;48145:283;;;;47361:652;;48249:17;;48280:18;;48312:16;;48342:12;;48145:283;:::i;:::-;;;;;;;;46382:2053;;;;46321:2114;:::o;53803:915::-;53884:18;;;;;;53860:21;53951:29;53894:7;53951:20;:29::i;:::-;53912:68;;43821:10;54069:11;:20;;;:35;;;;:::i;:::-;54050:15;:54;54046:88;;54113:21;;;;;;;;;;;;;;54046:88;54244:22;54211:29;;;;:14;:29;;;;;;;;;;;;:55;;;;;;;:::i;:::-;;54207:85;;54275:17;;;;;;;;;;;;;;54207:85;54302:29;;;;54334:21;54302:29;;;;;;;;:53;;-1:-1:-1;;54302:53:0;;54334:21;54302:53;;;;-1:-1:-1;54441:24:0;;;;54491:23;;;;54568:27;;;;54541:24;;;;54428:10;;54541:54;;;:::i;:::-;54524:71;-1:-1:-1;54605:35:0;-1:-1:-1;;;;;54605:23:0;;54629:2;54524:71;54605:23;:35::i;:::-;54656:55;;;-1:-1:-1;;;;;11073:55:1;;;11055:74;;11160:2;11145:18;;11138:34;;;54656:55:0;;;54678:13;;54656:55;;11028:18:1;54656:55:0;;;;;;;53850:868;;;;;53803:915;:::o;41542:199::-;41638:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41602:48;;;;;;41660:35;40261:25;41686:8;41660:11;:35::i;:::-;-1:-1:-1;41710:24:0;;-1:-1:-1;;;;;10143:55:1;;10125:74;;41710:24:0;;10113:2:1;10098:18;41710:24:0;9979:226:1;41747:181:0;41836:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41800:48;;;;;;41858:30;40329:23;41881:6;41858:10;:30::i;:::-;-1:-1:-1;41903:18:0;;-1:-1:-1;;;;;10143:55:1;;10125:74;;41903:18:0;;10113:2:1;10098:18;41903::0;9979:226:1;50218:793:0;41062:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41032:69;;;;;;;10412:2:1;41032:69:0;;;10394:21:1;10451:2;10431:18;;;10424:30;10490:25;10470:18;;;10463:53;10533:18;;41032:69:0;10210:347:1;41032:69:0;50330:18;;::::1;::::0;::::1;::::0;50306:21:::1;50397:29;50340:7:::0;50397:20:::1;:29::i;:::-;50358:68;;43821:10;50522:11;:20;;;:35;;;;:::i;:::-;50504:15;:53;50500:84;;;50566:18;;;;;;;;;;;;;;50500:84;50688:22;50655:29;::::0;;;:14:::1;:29;::::0;;;;;;;;::::1;;::::0;:55;::::1;;;;;;:::i;:::-;;50651:85;;50719:17;;;;;;;;;;;;;;50651:85;50746:29;::::0;;;:14:::1;:29;::::0;;;;;;;:59;;50778:27:::1;-1:-1:-1::0;;50746:59:0;;::::1;;::::0;;50845:70;;;;::::1;::::0;;::::1;50876:15;50845:70:::0;::::1;::::0;;50903:10:::1;50845:70:::0;;::::1;::::0;;;50815:27;;;:12:::1;:27:::0;;;;;;:100;;;;-1:-1:-1;;;;;50815:100:0::1;::::0;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;50946:58;785:25:1;;;50746:29:0;;50946:58:::1;::::0;758:18:1;50946:58:0::1;;;;;;;50296:715;;50218:793:::0;;:::o;48473:1707::-;41062:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41032:69;;;;;;;10412:2:1;41032:69:0;;;10394:21:1;10451:2;10431:18;;;10424:30;10490:25;10470:18;;;10463:53;10533:18;;41032:69:0;10210:347:1;41032:69:0;48573:18;;::::1;::::0;::::1;::::0;48549:21:::1;48640:29;48583:7:::0;48640:20:::1;:29::i;:::-;48601:68;;48717:13;48683:48;;:11;:23;;;:48;;;48679:77;;48740:16;;;;;;;;;;;;;;48679:77;48852:11;:20;;;48834:15;:38;48830:69;;;48881:18;;;;;;;;;;;;;;48830:69;48960:27;::::0;;;:12:::1;:27;::::0;;;;;::::1;;48956:60;;;48996:20;;;;;;;;;;;;;;48956:60;49026:27;::::0;;;:12:::1;:27;::::0;;;;:34;;-1:-1:-1;;49026:34:0::1;49056:4;49026:34;::::0;;49173:25:::1;::::0;::::1;::::0;49224:21:::1;::::0;::::1;::::0;49272:22:::1;::::0;::::1;::::0;49322:14:::1;::::0;49351:24:::1;::::0;::::1;::::0;49346:517:::1;;-1:-1:-1::0;49429:1:0::1;49444:29;49455:2:::0;49459:5;49466:6;49444:10:::1;:29::i;:::-;;49346:517;;;49494:38:::0;-1:-1:-1;;;;;49494:38:0;::::1;::::0;49490:373:::1;;49614:38;49625:2:::0;49629:5;49636:15:::1;49645:6:::0;49636;:15:::1;:::i;:::-;49614:10;:38::i;49490:373::-;49756:29;49767:2;49771:5;49778:6;49756:10;:29::i;:::-;;49799:53;49810:2;37662:42;49845:6;49799:10;:53::i;:::-;;49490:373;49972:25:::0;;50011:23:::1;::::0;;::::1;::::0;50048:21:::1;::::0;;::::1;::::0;50083:24:::1;::::0;;::::1;::::0;50121:22:::1;::::0;::::1;::::0;49878:295:::1;::::0;;13557:10:1;13545:23;;;13527:42;;-1:-1:-1;;;;;13666:15:1;;;13661:2;13646:18;;13639:43;13718:15;;;13698:18;;;13691:43;;;;13765:2;13750:18;;13743:34;13793:19;;;13786:35;13837:19;;13830:35;;;49878:295:0;::::1;::::0;49932:10:::1;::::0;49905:13;;49878:295:::1;::::0;13499:19:1;49878:295:0::1;13242:629:1::0;51667:373:0;51748:4;51801:27;51768:29;;;;:14;:29;;;;;;;;;;;;:60;;;;;;;:::i;:::-;;51764:90;;51837:17;;;;;;;;;;;;;;51764:90;51864:24;51891:27;;;:12;:27;;;;;;;;;51864:54;;;;;;;;;;;;;;-1:-1:-1;;;;;51864:54:0;;;;;;;;;;;;51932:24;;;51928:54;;51965:17;;;;;;;;;;;;;;51928:54;51597:15;;43687:10;;51578:15;51571:41;51563:49;;51999:34;;51667:373;-1:-1:-1;;;;51667:373:0:o;46120:163::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46236:40:0;;-1:-1:-1;;46236:40:0;;;;;;;;;;:::i;53251:514::-;40938:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;40910:65;;;;;;;15688:2:1;40910:65:0;;;15670:21:1;15727:2;15707:18;;;15700:30;15766:23;15746:18;;;15739:51;15807:18;;40910:65:0;15486:345:1;40910:65:0;53357:27:::1;53324:29;::::0;;;:14:::1;:29;::::0;;;;;;;;::::1;;::::0;:60;::::1;;;;;;:::i;:::-;;53320:90;;53393:17;;;;;;;;;;;;;;53320:90;53435:27;::::0;;;:12:::1;:27;::::0;;;;;;;;53424:39;;;;::::1;::::0;;;;::::1;::::0;;::::1;::::0;;;;;;::::1;-1:-1:-1::0;;;;;53424:39:0::1;::::0;;;::::1;::::0;;;;43687:10:::1;::::0;51578:15;51571:41;51563:49;53424:56:::1;53420:90;;;53489:21;;;;;;;;;;;;;;53420:90;53598:29;::::0;;;:14:::1;:29;::::0;;;;;;;:54;;-1:-1:-1;;53598:54:0::1;53630:22;53598:54;::::0;;53669:12:::1;:27:::0;;;;;;53662:34;;;53712:46;53747:10:::1;::::0;53598:29;;53712:46:::1;::::0;53598:29;53712:46:::1;53251:514:::0;:::o;42543:279::-;41190:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41159:71;;;;;;;9425:2:1;41159:71:0;;;9407:21:1;9464:2;9444:18;;;9437:30;9503:26;9483:18;;;9476:54;9547:18;;41159:71:0;9223:348:1;41159:71:0;40513:6:::1;42631:10;:26;;42623:55;;;::::0;::::1;::::0;;16038:2:1;42623:55:0::1;::::0;::::1;16020:21:1::0;16077:2;16057:18;;;16050:30;16116:18;16096;;;16089:46;16152:18;;42623:55:0::1;15836:340:1::0;42623:55:0::1;42709:15;::::0;;42734:28;;;;42777:38:::1;::::0;;16355:25:1;;;16411:2;16396:18;;16389:34;;;42777:38:0::1;::::0;16328:18:1;42777:38:0::1;;;;;;;;42613:209;42543:279:::0;:::o;43182:253::-;41190:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41159:71;;;;;;;9425:2:1;41159:71:0;;;9407:21:1;9464:2;9444:18;;;9437:30;9503:26;9483:18;;;9476:54;9547:18;;41159:71:0;9223:348:1;41159:71:0;43296:14:::1;::::0;;43320:34;;;;43369:59:::1;::::0;;16355:25:1;;;16411:2;16396:18;;16389:34;;;43369:59:0::1;::::0;16328:18:1;43369:59:0::1;16181:248:1::0;41934:187:0;42026:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41990:48;;;;;;42048:31;40329:23;42072:6;42048:11;:31::i;:::-;-1:-1:-1;42094:20:0;;-1:-1:-1;;;;;10143:55:1;;10125:74;;42094:20:0;;10113:2:1;10098:18;42094:20:0;9979:226:1;35110:138:0;34343:7;34369:12;;;;;;;;;;:22;;;32932:16;32943:4;32932:10;:16::i;:::-;35215:26:::1;35227:4;35233:7;35215:11;:26::i;41343:193::-:0;41436:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41400:48;;;;;;41458:34;40261:25;41483:8;41458:10;:34::i;:::-;-1:-1:-1;41507:22:0;;-1:-1:-1;;;;;10143:55:1;;10125:74;;41507:22:0;;10113:2:1;10098:18;41507:22:0;9979:226:1;42332:205:0;42430:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;42394:48;;;;;;42452:37;40398:26;42479:9;42452:11;:37::i;:::-;-1:-1:-1;42504:26:0;;-1:-1:-1;;;;;10143:55:1;;10125:74;;42504:26:0;;10113:2:1;10098:18;42504:26:0;9979:226:1;37945:653:0;38120:4;-1:-1:-1;;;;;38106:19:0;;;38102:32;;37945:653;;;:::o;38102:32::-;38206:5;38215:1;38206:10;38202:23;;37945:653;;;:::o;38202:23::-;38238:20;-1:-1:-1;;;;;38238:20:0;;;38234:358;;38418:12;38435:2;-1:-1:-1;;;;;38435:7:0;38450:5;38435:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38417:43;;;38482:7;38474:39;;;;;;;16846:2:1;38474:39:0;;;16828:21:1;16885:2;16865:18;;;16858:30;16924:21;16904:18;;;16897:49;16963:18;;38474:39:0;16644:343:1;38234:358:0;38544:37;-1:-1:-1;;;;;38544:26:0;;38571:2;38575:5;38544:26;:37::i;33667:103::-;33733:30;33744:4;22980:10;33733;:30::i;:::-;33667:103;:::o;36647:316::-;36724:4;33422:12;;;;;;;;;;;-1:-1:-1;;;;;33422:29:0;;;;;;;;;;;;36740:217;;36783:6;:12;;;;;;;;;;;-1:-1:-1;;;;;36783:29:0;;;;;;;;;:36;;-1:-1:-1;;36783:36:0;36815:4;36783:36;;;36865:12;22980:10;;22901:96;36865:12;-1:-1:-1;;;;;36838:40:0;36856:7;-1:-1:-1;;;;;36838:40:0;36850:4;36838:40;;;;;;;;;;-1:-1:-1;36899:4:0;36892:11;;36740:217;-1:-1:-1;36941:5:0;36934:12;;37198:317;37276:4;33422:12;;;;;;;;;;;-1:-1:-1;;;;;33422:29:0;;;;;;;;;;;;37292:217;;;37366:5;37334:12;;;;;;;;;;;-1:-1:-1;;;;;37334:29:0;;;;;;;;;;:37;;-1:-1:-1;;37334:37:0;;;37390:40;22980:10;;37334:12;;37390:40;;37366:5;37390:40;-1:-1:-1;37451:4:0;37444:11;;44905:1177;44993:20;-1:-1:-1;;;;;45029:38:0;;37662:42;45029:38;45025:1051;;45083:24;:5;-1:-1:-1;;;;;45083:22:0;;:24::i;:::-;45188:34;;;;;-1:-1:-1;;;;;10143:55:1;;;45188:34:0;;;10125:74:1;45188:23:0;;;;;10098:18:1;;45188:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;45173:49;-1:-1:-1;45368:61:0;-1:-1:-1;;;;;45368:30:0;;45399:10;45411:9;45422:6;45368:30;:61::i;:::-;45565:34;;;;;-1:-1:-1;;;;;10143:55:1;;;45565:34:0;;;10125:74:1;45602:12:0;;45565:23;;;;;;10098:18:1;;45565:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:49;;;;:::i;:::-;45550:64;;45025:1051;;;45736:9;45726:6;:19;45722:51;;45754:19;;;;;;;;;;;;;;45722:51;-1:-1:-1;;;;;45854:26:0;;45875:4;45854:26;45850:74;;45882:42;-1:-1:-1;;;;;45882:23:0;;45906:9;45917:6;45882:23;:42::i;:::-;-1:-1:-1;46056:9:0;45025:1051;44905:1177;;;;;:::o;26150:160::-;26259:43;;-1:-1:-1;;;;;11073:55:1;;;26259:43:0;;;11055:74:1;11145:18;;;11138:34;;;26232:71:0;;26252:5;;26274:14;;;;;11028:18:1;;26259:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26232:19;:71::i;33900:197::-;33399:4;33422:12;;;;;;;;;;;-1:-1:-1;;;;;33422:29:0;;;;;;;;;;;;33983:108;;34033:47;;;;;-1:-1:-1;;;;;11073:55:1;;34033:47:0;;;11055:74:1;11145:18;;;11138:34;;;11028:18;;34033:47:0;10881:297:1;39762:344:0;39929:38;-1:-1:-1;;;;;39929:38:0;;;39925:69;;39976:18;;;;;;;;;;;;;;39925:69;40050:5;-1:-1:-1;;;;;40050:17:0;;40071:1;40050:22;40046:53;;40081:18;;;;;;;;;;;;;;26549:188;26676:53;;-1:-1:-1;;;;;9857:15:1;;;26676:53:0;;;9839:34:1;9909:15;;;9889:18;;;9882:43;9941:18;;;9934:34;;;26649:81:0;;26669:5;;26691:18;;;;;9751::1;;26676:53:0;9576:398:1;28906:629:0;29325:23;29351:33;-1:-1:-1;;;;;29351:27:0;;29379:4;29351:27;:33::i;:::-;29325:59;;29398:10;:17;29419:1;29398:22;;:57;;;;;29436:10;29425:30;;;;;;;;;;;;:::i;:::-;29424:31;29398:57;29394:135;;;29478:40;;;;;-1:-1:-1;;;;;10143:55:1;;29478:40:0;;;10125:74:1;10098:18;;29478:40:0;9979:226:1;18686:151:0;18761:12;18792:38;18814:6;18822:4;18828:1;18761:12;19402;19416:23;19443:6;-1:-1:-1;;;;;19443:11:0;19462:5;19469:4;19443:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19401:73;;;;19491:55;19518:6;19526:7;19535:10;19491:26;:55::i;:::-;19484:62;19161:392;-1:-1:-1;;;;;;19161:392:0:o;20606:582::-;20750:12;20779:7;20774:408;;20802:19;20810:10;20802:7;:19::i;:::-;20774:408;;;21026:17;;:22;:49;;;;-1:-1:-1;;;;;;21052:18:0;;;:23;21026:49;21022:119;;;21102:24;;;;;-1:-1:-1;;;;;10143:55:1;;21102:24:0;;;10125:74:1;10098:18;;21102:24:0;9979:226:1;21022:119:0;-1:-1:-1;21161:10:0;21154:17;;21724:516;21855:17;;:21;21851:383;;22083:10;22077:17;22139:15;22126:10;22122:2;22118:19;22111:44;21851:383;22206:17;;;;;;;;;;;;;;14:332:1;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;180:9;167:23;230:66;223:5;219:78;212:5;209:89;199:117;;312:1;309;302:12;821:180;880:6;933:2;921:9;912:7;908:23;904:32;901:52;;;949:1;946;939:12;901:52;-1:-1:-1;972:23:1;;821:180;-1:-1:-1;821:180:1:o;1006:184::-;1058:77;1055:1;1048:88;1155:4;1152:1;1145:15;1179:4;1176:1;1169:15;1195:402;1344:2;1329:18;;1377:1;1366:13;;1356:201;;1413:77;1410:1;1403:88;1514:4;1511:1;1504:15;1542:4;1539:1;1532:15;1356:201;1566:25;;;1195:402;:::o;1602:154::-;-1:-1:-1;;;;;1681:5:1;1677:54;1670:5;1667:65;1657:93;;1746:1;1743;1736:12;1761:134;1829:20;;1858:31;1829:20;1858:31;:::i;:::-;1761:134;;;:::o;1900:388::-;1968:6;1976;2029:2;2017:9;2008:7;2004:23;2000:32;1997:52;;;2045:1;2042;2035:12;1997:52;2084:9;2071:23;2103:31;2128:5;2103:31;:::i;:::-;2153:5;-1:-1:-1;2210:2:1;2195:18;;2182:32;2223:33;2182:32;2223:33;:::i;:::-;2275:7;2265:17;;;1900:388;;;;;:::o;2475:315::-;2543:6;2551;2604:2;2592:9;2583:7;2579:23;2575:32;2572:52;;;2620:1;2617;2610:12;2572:52;2656:9;2643:23;2633:33;;2716:2;2705:9;2701:18;2688:32;2729:31;2754:5;2729:31;:::i;2795:247::-;2854:6;2907:2;2895:9;2886:7;2882:23;2878:32;2875:52;;;2923:1;2920;2913:12;2875:52;2962:9;2949:23;2981:31;3006:5;2981:31;:::i;3047:184::-;3099:77;3096:1;3089:88;3196:4;3193:1;3186:15;3220:4;3217:1;3210:15;3236:252;3308:2;3302:9;3350:3;3338:16;;3384:18;3369:34;;3405:22;;;3366:62;3363:88;;;3431:18;;:::i;:::-;3467:2;3460:22;3236:252;:::o;3493:247::-;3560:2;3554:9;3602:3;3590:16;;3636:18;3621:34;;3657:22;;;3618:62;3615:88;;;3683:18;;:::i;3745:777::-;3787:5;3840:3;3833:4;3825:6;3821:17;3817:27;3807:55;;3858:1;3855;3848:12;3807:55;3894:6;3881:20;3920:18;3957:2;3953;3950:10;3947:36;;;3963:18;;:::i;:::-;4097:2;4091:9;4159:4;4151:13;;4002:66;4147:22;;;4171:2;4143:31;4139:40;4127:53;;;4195:18;;;4215:22;;;4192:46;4189:72;;;4241:18;;:::i;:::-;4281:10;4277:2;4270:22;4316:2;4308:6;4301:18;4362:3;4355:4;4350:2;4342:6;4338:15;4334:26;4331:35;4328:55;;;4379:1;4376;4369:12;4328:55;4443:2;4436:4;4428:6;4424:17;4417:4;4409:6;4405:17;4392:54;4490:1;4483:4;4478:2;4470:6;4466:15;4462:26;4455:37;4510:6;4501:15;;;;;;3745:777;;;;:::o;4527:455::-;4604:6;4612;4665:2;4653:9;4644:7;4640:23;4636:32;4633:52;;;4681:1;4678;4671:12;4633:52;4721:9;4708:23;4754:18;4746:6;4743:30;4740:50;;;4786:1;4783;4776:12;4740:50;4809:49;4850:7;4841:6;4830:9;4826:22;4809:49;:::i;:::-;4799:59;;;4908:2;4897:9;4893:18;4880:32;4921:31;4946:5;4921:31;:::i;4987:121::-;5072:10;5065:5;5061:22;5054:5;5051:33;5041:61;;5098:1;5095;5088:12;5113:132;5180:20;;5209:30;5180:20;5209:30;:::i;5250:118::-;5336:5;5329:13;5322:21;5315:5;5312:32;5302:60;;5358:1;5355;5348:12;5373:128;5438:20;;5467:28;5438:20;5467:28;:::i;5506:865::-;5594:6;5647:3;5635:9;5626:7;5622:23;5618:33;5615:53;;;5664:1;5661;5654:12;5615:53;5690:22;;:::i;:::-;5735:28;5753:9;5735:28;:::i;:::-;5728:5;5721:43;5796:38;5830:2;5819:9;5815:18;5796:38;:::i;:::-;5791:2;5784:5;5780:14;5773:62;5867:38;5901:2;5890:9;5886:18;5867:38;:::i;:::-;5862:2;5855:5;5851:14;5844:62;5938:38;5972:2;5961:9;5957:18;5938:38;:::i;:::-;5933:2;5926:5;5922:14;5915:62;6010:39;6044:3;6033:9;6029:19;6010:39;:::i;:::-;6004:3;5997:5;5993:15;5986:64;6111:3;6100:9;6096:19;6083:33;6077:3;6070:5;6066:15;6059:58;6178:3;6167:9;6163:19;6150:33;6144:3;6137:5;6133:15;6126:58;6217:36;6248:3;6237:9;6233:19;6217:36;:::i;:::-;6211:3;6200:15;;6193:61;6273:3;6321:18;;;6308:32;6292:14;;;6285:56;;;;-1:-1:-1;6204:5:1;5506:865;-1:-1:-1;5506:865:1:o;6376:320::-;6444:6;6497:2;6485:9;6476:7;6472:23;6468:32;6465:52;;;6513:1;6510;6503:12;6465:52;6553:9;6540:23;6586:18;6578:6;6575:30;6572:50;;;6618:1;6615;6608:12;6572:50;6641:49;6682:7;6673:6;6662:9;6658:22;6641:49;:::i;:::-;6631:59;6376:320;-1:-1:-1;;;;6376:320:1:o;6701:388::-;6778:6;6786;6839:2;6827:9;6818:7;6814:23;6810:32;6807:52;;;6855:1;6852;6845:12;6807:52;6895:9;6882:23;6928:18;6920:6;6917:30;6914:50;;;6960:1;6957;6950:12;6914:50;6983:49;7024:7;7015:6;7004:9;7000:22;6983:49;:::i;:::-;6973:59;7079:2;7064:18;;;;7051:32;;-1:-1:-1;;;;6701:388:1:o;7658:1375::-;7891:13;;7635:10;7624:22;7612:35;;7860:3;7845:19;;7963:4;7955:6;7951:17;7945:24;7978:53;8025:4;8014:9;8010:20;7996:12;7635:10;7624:22;7612:35;;7559:94;7978:53;;8080:4;8072:6;8068:17;8062:24;8095:56;8145:4;8134:9;8130:20;8114:14;-1:-1:-1;;;;;7160:54:1;7148:67;;7094:127;8095:56;;8200:4;8192:6;8188:17;8182:24;8215:56;8265:4;8254:9;8250:20;8234:14;-1:-1:-1;;;;;7160:54:1;7148:67;;7094:127;8215:56;;8320:4;8312:6;8308:17;8302:24;8335:56;8385:4;8374:9;8370:20;8354:14;-1:-1:-1;;;;;7160:54:1;7148:67;;7094:127;8335:56;;8440:4;8432:6;8428:17;8422:24;8455:56;8505:4;8494:9;8490:20;8474:14;-1:-1:-1;;;;;7160:54:1;7148:67;;7094:127;8455:56;;8567:4;8559:6;8555:17;8549:24;8542:4;8531:9;8527:20;8520:54;8630:4;8622:6;8618:17;8612:24;8605:4;8594:9;8590:20;8583:54;8656:6;8716:2;8708:6;8704:15;8698:22;8693:2;8682:9;8678:18;8671:50;;8740:6;8795:2;8787:6;8783:15;8777:22;8808:51;8855:2;8844:9;8840:18;8824:14;421:13;414:21;402:34;;351:91;8808:51;-1:-1:-1;;8878:6:1;8926:15;;;8920:22;8900:18;;;8893:50;8962:6;9010:15;;;9004:22;8984:18;;;;8977:50;;;;7658:1375;:::o;10562:184::-;10614:77;10611:1;10604:88;10711:4;10708:1;10701:15;10735:4;10732:1;10725:15;10751:125;10816:9;;;10837:10;;;10834:36;;;10850:18;;:::i;11183:168::-;11256:9;;;11287;;11304:15;;;11298:22;;11284:37;11274:71;;11325:18;;:::i;11356:274::-;11396:1;11422;11412:189;;11457:77;11454:1;11447:88;11558:4;11555:1;11548:15;11586:4;11583:1;11576:15;11412:189;-1:-1:-1;11615:9:1;;11356:274::o;11635:128::-;11702:9;;;11723:11;;;11720:37;;;11737:18;;:::i;11768:195::-;11807:3;11838:66;11831:5;11828:77;11825:103;;11908:18;;:::i;:::-;-1:-1:-1;11955:1:1;11944:13;;11768:195::o;11968:250::-;12053:1;12063:113;12077:6;12074:1;12071:13;12063:113;;;12153:11;;;12147:18;12134:11;;;12127:39;12099:2;12092:10;12063:113;;;-1:-1:-1;;12210:1:1;12192:16;;12185:27;11968:250::o;12223:1014::-;12530:3;12519:9;12512:22;12493:4;12563:6;12557:13;12607:6;12601:3;12590:9;12586:19;12579:35;12633:3;12645:81;12719:6;12714:2;12703:9;12699:18;12692:4;12684:6;12680:17;12645:81;:::i;:::-;12906:10;12894:23;;;;12887:4;12872:20;;12865:53;-1:-1:-1;;;;;13015:15:1;;;13010:2;12995:18;;12988:43;13067:15;;;;13062:2;13047:18;;13040:43;13114:3;13099:19;;13092:35;;;;13158:3;13143:19;;13136:35;;;;13215:14;13208:22;13202:3;13187:19;;13180:51;12778:2;12766:15;;;-1:-1:-1;12762:88:1;12747:104;12743:113;;;;;-1:-1:-1;;12223:1014:1:o;13876:136::-;13954:13;;13976:30;13954:13;13976:30;:::i;14017:138::-;14096:13;;14118:31;14096:13;14118:31;:::i;14160:132::-;14236:13;;14258:28;14236:13;14258:28;:::i;14297:1184::-;14401:6;14454:3;14442:9;14433:7;14429:23;14425:33;14422:53;;;14471:1;14468;14461:12;14422:53;14497:17;;:::i;:::-;14537:39;14566:9;14537:39;:::i;:::-;14530:5;14523:54;14609:48;14653:2;14642:9;14638:18;14609:48;:::i;:::-;14604:2;14597:5;14593:14;14586:72;14690:49;14735:2;14724:9;14720:18;14690:49;:::i;:::-;14685:2;14678:5;14674:14;14667:73;14772:49;14817:2;14806:9;14802:18;14772:49;:::i;:::-;14767:2;14760:5;14756:14;14749:73;14855:50;14900:3;14889:9;14885:19;14855:50;:::i;:::-;14849:3;14842:5;14838:15;14831:75;14939:50;14984:3;14973:9;14969:19;14939:50;:::i;:::-;14933:3;14926:5;14922:15;14915:75;15044:3;15033:9;15029:19;15023:26;15017:3;15010:5;15006:15;14999:51;15104:3;15093:9;15089:19;15083:26;15077:3;15070:5;15066:15;15059:51;15129:3;15185:2;15174:9;15170:18;15164:25;15159:2;15152:5;15148:14;15141:49;;15209:3;15244:46;15286:2;15275:9;15271:18;15244:46;:::i;:::-;15228:14;;;15221:70;15310:3;15351:18;;;15345:25;15329:14;;;15322:49;15390:3;15431:18;;;15425:25;15409:14;;;15402:49;;;;-1:-1:-1;15232:5:1;14297:1184;-1:-1:-1;14297:1184:1:o;16992:184::-;17062:6;17115:2;17103:9;17094:7;17090:23;17086:32;17083:52;;;17131:1;17128;17121:12;17083:52;-1:-1:-1;17154:16:1;;16992:184;-1:-1:-1;16992:184:1:o;17483:245::-;17550:6;17603:2;17591:9;17582:7;17578:23;17574:32;17571:52;;;17619:1;17616;17609:12;17571:52;17651:9;17645:16;17670:28;17692:5;17670:28;:::i;17733:287::-;17862:3;17900:6;17894:13;17916:66;17975:6;17970:3;17963:4;17955:6;17951:17;17916:66;:::i;:::-;17998:16;;;;;17733:287;-1:-1:-1;;17733:287:1:o","abiDefinition":[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"AmountIncorrect","type":"error"},{"inputs":[],"name":"ChainIncorrect","type":"error"},{"inputs":[],"name":"DeadlineExceeded","type":"error"},{"inputs":[],"name":"DeadlineNotExceeded","type":"error"},{"inputs":[],"name":"DeadlineTooShort","type":"error"},{"inputs":[],"name":"DisputePeriodNotPassed","type":"error"},{"inputs":[],"name":"DisputePeriodPassed","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"MsgValueIncorrect","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"SenderIncorrect","type":"error"},{"inputs":[],"name":"StatusIncorrect","type":"error"},{"inputs":[],"name":"TokenNotContract","type":"error"},{"inputs":[],"name":"TransactionRelayed","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositRefunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"}],"name":"BridgeProofDisputed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":false,"internalType":"bytes32","name":"transactionHash","type":"bytes32"}],"name":"BridgeProofProvided","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint32","name":"originChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"chainGasAmount","type":"uint256"}],"name":"BridgeRelayed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes","name":"request","type":"bytes"},{"indexed":false,"internalType":"uint32","name":"destChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"sendChainGas","type":"bool"}],"name":"BridgeRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldChainGasAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"ChainGasAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFeeRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"FeeRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesSwept","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"governor","type":"address"}],"name":"GovernorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"governor","type":"address"}],"name":"GovernorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guard","type":"address"}],"name":"GuardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guard","type":"address"}],"name":"GuardRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DISPUTE_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_RATE_MAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GOVERNOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GUARD_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_DEADLINE_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROVE_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAYER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_governor","type":"address"}],"name":"addGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guard","type":"address"}],"name":"addGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_relayer","type":"address"}],"name":"addRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstChainId","type":"uint32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IFastBridge.BridgeParams","name":"params","type":"tuple"}],"name":"bridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"bridgeProofs","outputs":[{"internalType":"uint96","name":"timestamp","type":"uint96"},{"internalType":"address","name":"relayer","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"bridgeRelays","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"bridgeStatuses","outputs":[{"internalType":"enum FastBridge.BridgeStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"address","name":"relayer","type":"address"}],"name":"canClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainGasAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"address","name":"to","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deployBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"dispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"getBridgeTransaction","outputs":[{"components":[{"internalType":"uint32","name":"originChainId","type":"uint32"},{"internalType":"uint32","name":"destChainId","type":"uint32"},{"internalType":"address","name":"originSender","type":"address"},{"internalType":"address","name":"destRecipient","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256","name":"originFeeAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct IFastBridge.BridgeTransaction","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"protocolFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"bytes32","name":"destTxHash","type":"bytes32"}],"name":"prove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"relay","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_governor","type":"address"}],"name":"removeGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guard","type":"address"}],"name":"removeGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_relayer","type":"address"}],"name":"removeRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"setChainGasAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"setProtocolFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"sweepProtocolFees","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"DISPUTE_PERIOD()":{"notice":"Dispute period for relayed transactions"},"MIN_DEADLINE_PERIOD()":{"notice":"Minimum deadline period to relay a requested bridge transaction"},"PROVE_PERIOD()":{"notice":"Prove period added to deadline period for proven transactions"},"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"notice":"Initiates bridge on origin chain to be relayed by off-chain relayer"},"bridgeProofs(bytes32)":{"notice":"Proof of relayed bridge tx on origin chain"},"bridgeRelays(bytes32)":{"notice":"Whether bridge has been relayed on destination chain"},"bridgeStatuses(bytes32)":{"notice":"Status of the bridge tx on origin chain"},"canClaim(bytes32,address)":{"notice":"Checks if the dispute period has passed so bridge deposit can be claimed"},"chainGasAmount()":{"notice":"Chain gas amount to forward as rebate if requested"},"claim(bytes,address)":{"notice":"Completes bridge transaction on origin chain by claiming originally deposited capital"},"dispute(bytes32)":{"notice":"Disputes an outstanding proof in case relayer provided dest chain tx is invalid"},"getBridgeTransaction(bytes)":{"notice":"Decodes bridge request into a bridge transaction"},"protocolFeeRate()":{"notice":"Protocol fee rate taken on origin amount deposited in origin chain"},"protocolFees(address)":{"notice":"Protocol fee amounts accumulated"},"prove(bytes,bytes32)":{"notice":"Provides proof on origin side that relayer provided funds on destination side of bridge transaction"},"refund(bytes)":{"notice":"Refunds an outstanding bridge transaction in case optimistic bridging failed"},"relay(bytes)":{"notice":"Relays destination side of bridge transaction by off-chain relayer"}},"version":1},"developerDoc":{"errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}],"AddressEmptyCode(address)":[{"details":"There's no code at `target` (it is not a contract)."}],"AddressInsufficientBalance(address)":[{"details":"The ETH balance of the account is not enough to perform the operation."}],"FailedInnerCall()":[{"details":"A call to an address target failed. The target may have reverted."}],"SafeERC20FailedOperation(address)":[{"details":"An operation with an ERC-20 token failed."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"params":{"params":"The parameters required to bridge"}},"canClaim(bytes32,address)":{"params":{"relayer":"The address of the relayer attempting to claim","transactionId":"The transaction id associated with the encoded bridge transaction to check"}},"claim(bytes,address)":{"params":{"request":"The encoded bridge transaction to claim on origin chain","to":"The recipient address of the funds"}},"dispute(bytes32)":{"params":{"transactionId":"The transaction id associated with the encoded bridge transaction to dispute"}},"getBridgeTransaction(bytes)":{"params":{"request":"The bridge request to decode"}},"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"prove(bytes,bytes32)":{"params":{"destTxHash":"The destination tx hash proving bridge transaction was relayed","request":"The encoded bridge transaction to prove on origin chain"}},"refund(bytes)":{"params":{"request":"The encoded bridge transaction to refund"}},"relay(bytes)":{"params":{"request":"The encoded bridge transaction to relay on destination chain"}},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"stateVariables":{"nonce":{"details":"to prevent replays"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineNotExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineTooShort\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputePeriodNotPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputePeriodPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MsgValueIncorrect\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SenderIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StatusIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenNotContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransactionRelayed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositRefunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"BridgeProofDisputed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"transactionHash\",\"type\":\"bytes32\"}],\"name\":\"BridgeProofProvided\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"BridgeRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"}],\"name\":\"BridgeRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DISPUTE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_DEADLINE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROVE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"addGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"addGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"addRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"bridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeProofs\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"timestamp\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeRelays\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeStatuses\",\"outputs\":[{\"internalType\":\"enum FastBridge.BridgeStatus\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"canClaim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"dispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"getBridgeTransaction\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originSender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destRecipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originFeeAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeTransaction\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"destTxHash\",\"type\":\"bytes32\"}],\"name\":\"prove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"refund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"removeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"removeGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"removeRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}],\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"AddressInsufficientBalance(address)\":[{\"details\":\"The ETH balance of the account is not enough to perform the operation.\"}],\"FailedInnerCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"params\":{\"params\":\"The parameters required to bridge\"}},\"canClaim(bytes32,address)\":{\"params\":{\"relayer\":\"The address of the relayer attempting to claim\",\"transactionId\":\"The transaction id associated with the encoded bridge transaction to check\"}},\"claim(bytes,address)\":{\"params\":{\"request\":\"The encoded bridge transaction to claim on origin chain\",\"to\":\"The recipient address of the funds\"}},\"dispute(bytes32)\":{\"params\":{\"transactionId\":\"The transaction id associated with the encoded bridge transaction to dispute\"}},\"getBridgeTransaction(bytes)\":{\"params\":{\"request\":\"The bridge request to decode\"}},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"prove(bytes,bytes32)\":{\"params\":{\"destTxHash\":\"The destination tx hash proving bridge transaction was relayed\",\"request\":\"The encoded bridge transaction to prove on origin chain\"}},\"refund(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to refund\"}},\"relay(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to relay on destination chain\"}},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"stateVariables\":{\"nonce\":{\"details\":\"to prevent replays\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DISPUTE_PERIOD()\":{\"notice\":\"Dispute period for relayed transactions\"},\"MIN_DEADLINE_PERIOD()\":{\"notice\":\"Minimum deadline period to relay a requested bridge transaction\"},\"PROVE_PERIOD()\":{\"notice\":\"Prove period added to deadline period for proven transactions\"},\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"notice\":\"Initiates bridge on origin chain to be relayed by off-chain relayer\"},\"bridgeProofs(bytes32)\":{\"notice\":\"Proof of relayed bridge tx on origin chain\"},\"bridgeRelays(bytes32)\":{\"notice\":\"Whether bridge has been relayed on destination chain\"},\"bridgeStatuses(bytes32)\":{\"notice\":\"Status of the bridge tx on origin chain\"},\"canClaim(bytes32,address)\":{\"notice\":\"Checks if the dispute period has passed so bridge deposit can be claimed\"},\"chainGasAmount()\":{\"notice\":\"Chain gas amount to forward as rebate if requested\"},\"claim(bytes,address)\":{\"notice\":\"Completes bridge transaction on origin chain by claiming originally deposited capital\"},\"dispute(bytes32)\":{\"notice\":\"Disputes an outstanding proof in case relayer provided dest chain tx is invalid\"},\"getBridgeTransaction(bytes)\":{\"notice\":\"Decodes bridge request into a bridge transaction\"},\"protocolFeeRate()\":{\"notice\":\"Protocol fee rate taken on origin amount deposited in origin chain\"},\"protocolFees(address)\":{\"notice\":\"Protocol fee amounts accumulated\"},\"prove(bytes,bytes32)\":{\"notice\":\"Provides proof on origin side that relayer provided funds on destination side of bridge transaction\"},\"refund(bytes)\":{\"notice\":\"Refunds an outstanding bridge transaction in case optimistic bridging failed\"},\"relay(bytes)\":{\"notice\":\"Relays destination side of bridge transaction by off-chain relayer\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"FastBridge\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x5838f2ff3b1c4e6b40f973a29cce9f16871bd7a03add5aeeb7f876df39e92167\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://220c9bc7c31596b7d0ad7806037a3ebaed6c271c84df15e3789d850deef3fb1a\",\"dweb:/ipfs/QmU3xjtrAqz9fBLJKHC8Q4LCXpTi77i2oJJbu5Q5Ex2h4J\"]}},\"version\":1}"},"hashes":{"DEFAULT_ADMIN_ROLE()":"a217fddf","DISPUTE_PERIOD()":"a5bbe22b","FEE_BPS()":"bf333f2c","FEE_RATE_MAX()":"0f5f6ed7","GOVERNOR_ROLE()":"ccc57490","GUARD_ROLE()":"03ed0ee5","MIN_DEADLINE_PERIOD()":"820688d5","PROVE_PERIOD()":"d3cbc760","RELAYER_ROLE()":"926d7d7f","addGovernor(address)":"3c4a25d0","addGuard(address)":"6913a63c","addRelayer(address)":"dd39f00d","bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":"45851694","bridgeProofs(bytes32)":"91ad5039","bridgeRelays(bytes32)":"8379a24f","bridgeStatuses(bytes32)":"051287bc","canClaim(bytes32,address)":"aa9641ab","chainGasAmount()":"e00a83e0","claim(bytes,address)":"41fcb612","deployBlock()":"a3ec191a","dispute(bytes32)":"add98c70","getBridgeTransaction(bytes)":"ac11fb1a","getRoleAdmin(bytes32)":"248a9ca3","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","nonce()":"affed0e0","protocolFeeRate()":"58f85880","protocolFees(address)":"dcf844a7","prove(bytes,bytes32)":"886d36ff","refund(bytes)":"5eb7d946","relay(bytes)":"8f0d6f17","removeGovernor(address)":"eecdac88","removeGuard(address)":"b6235016","removeRelayer(address)":"60f0a5ac","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","setChainGasAmount(uint256)":"b250fe6b","setProtocolFeeRate(uint256)":"b13aa2d6","supportsInterface(bytes4)":"01ffc9a7","sweepProtocolFees(address,address)":"06f333f2"}},"solidity/FastBridge.sol:IAccessControl":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"External interface of AccessControl declared to support ERC-165 detection.","errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {AccessControl-_setRoleAdmin}."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"External interface of AccessControl declared to support ERC-165 detection.\",\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {AccessControl-_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"IAccessControl\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x5838f2ff3b1c4e6b40f973a29cce9f16871bd7a03add5aeeb7f876df39e92167\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://220c9bc7c31596b7d0ad7806037a3ebaed6c271c84df15e3789d850deef3fb1a\",\"dweb:/ipfs/QmU3xjtrAqz9fBLJKHC8Q4LCXpTi77i2oJJbu5Q5Ex2h4J\"]}},\"version\":1}"},"hashes":{"getRoleAdmin(bytes32)":"248a9ca3","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f"}},"solidity/FastBridge.sol:IAdmin":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldChainGasAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"ChainGasAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFeeRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"FeeRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesSwept","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"governor","type":"address"}],"name":"GovernorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"governor","type":"address"}],"name":"GovernorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guard","type":"address"}],"name":"GuardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guard","type":"address"}],"name":"GuardRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerRemoved","type":"event"},{"inputs":[{"internalType":"address","name":"_governor","type":"address"}],"name":"addGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guard","type":"address"}],"name":"addGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_relayer","type":"address"}],"name":"addRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_governor","type":"address"}],"name":"removeGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guard","type":"address"}],"name":"removeGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_relayer","type":"address"}],"name":"removeRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"setChainGasAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"setProtocolFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"sweepProtocolFees","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerRemoved\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"addGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"addGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"addRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"removeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"removeGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"removeRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"IAdmin\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x5838f2ff3b1c4e6b40f973a29cce9f16871bd7a03add5aeeb7f876df39e92167\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://220c9bc7c31596b7d0ad7806037a3ebaed6c271c84df15e3789d850deef3fb1a\",\"dweb:/ipfs/QmU3xjtrAqz9fBLJKHC8Q4LCXpTi77i2oJJbu5Q5Ex2h4J\"]}},\"version\":1}"},"hashes":{"addGovernor(address)":"3c4a25d0","addGuard(address)":"6913a63c","addRelayer(address)":"dd39f00d","removeGovernor(address)":"eecdac88","removeGuard(address)":"b6235016","removeRelayer(address)":"60f0a5ac","setChainGasAmount(uint256)":"b250fe6b","setProtocolFeeRate(uint256)":"b13aa2d6","sweepProtocolFees(address,address)":"06f333f2"}},"solidity/FastBridge.sol:IERC165":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Interface of the ERC-165 standard, as defined in the https://eips.ethereum.org/EIPS/eip-165[ERC]. Implementers can declare support of contract interfaces, which can then be queried by others ({ERC165Checker}). For an implementation, see {ERC165}.","kind":"dev","methods":{"supportsInterface(bytes4)":{"details":"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Interface of the ERC-165 standard, as defined in the https://eips.ethereum.org/EIPS/eip-165[ERC]. Implementers can declare support of contract interfaces, which can then be queried by others ({ERC165Checker}). For an implementation, see {ERC165}.\",\"kind\":\"dev\",\"methods\":{\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"IERC165\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x5838f2ff3b1c4e6b40f973a29cce9f16871bd7a03add5aeeb7f876df39e92167\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://220c9bc7c31596b7d0ad7806037a3ebaed6c271c84df15e3789d850deef3fb1a\",\"dweb:/ipfs/QmU3xjtrAqz9fBLJKHC8Q4LCXpTi77i2oJJbu5Q5Ex2h4J\"]}},\"version\":1}"},"hashes":{"supportsInterface(bytes4)":"01ffc9a7"}},"solidity/FastBridge.sol:IERC20":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Interface of the ERC-20 standard as defined in the ERC.","events":{"Approval(address,address,uint256)":{"details":"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance."},"Transfer(address,address,uint256)":{"details":"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero."}},"kind":"dev","methods":{"allowance(address,address)":{"details":"Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through {transferFrom}. This is zero by default. This value changes when {approve} or {transferFrom} are called."},"approve(address,uint256)":{"details":"Sets a `value` amount of tokens as the allowance of `spender` over the caller's tokens. Returns a boolean value indicating whether the operation succeeded. IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 Emits an {Approval} event."},"balanceOf(address)":{"details":"Returns the value of tokens owned by `account`."},"totalSupply()":{"details":"Returns the value of tokens in existence."},"transfer(address,uint256)":{"details":"Moves a `value` amount of tokens from the caller's account to `to`. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event."},"transferFrom(address,address,uint256)":{"details":"Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism. `value` is then deducted from the caller's allowance. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Interface of the ERC-20 standard as defined in the ERC.\",\"events\":{\"Approval(address,address,uint256)\":{\"details\":\"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance.\"},\"Transfer(address,address,uint256)\":{\"details\":\"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero.\"}},\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through {transferFrom}. This is zero by default. This value changes when {approve} or {transferFrom} are called.\"},\"approve(address,uint256)\":{\"details\":\"Sets a `value` amount of tokens as the allowance of `spender` over the caller's tokens. Returns a boolean value indicating whether the operation succeeded. IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 Emits an {Approval} event.\"},\"balanceOf(address)\":{\"details\":\"Returns the value of tokens owned by `account`.\"},\"totalSupply()\":{\"details\":\"Returns the value of tokens in existence.\"},\"transfer(address,uint256)\":{\"details\":\"Moves a `value` amount of tokens from the caller's account to `to`. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism. `value` is then deducted from the caller's allowance. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"IERC20\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x5838f2ff3b1c4e6b40f973a29cce9f16871bd7a03add5aeeb7f876df39e92167\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://220c9bc7c31596b7d0ad7806037a3ebaed6c271c84df15e3789d850deef3fb1a\",\"dweb:/ipfs/QmU3xjtrAqz9fBLJKHC8Q4LCXpTi77i2oJJbu5Q5Ex2h4J\"]}},\"version\":1}"},"hashes":{"allowance(address,address)":"dd62ed3e","approve(address,uint256)":"095ea7b3","balanceOf(address)":"70a08231","totalSupply()":"18160ddd","transfer(address,uint256)":"a9059cbb","transferFrom(address,address,uint256)":"23b872dd"}},"solidity/FastBridge.sol:IERC20Permit":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in https://eips.ethereum.org/EIPS/eip-2612[ERC-2612]. Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't need to send a transaction, and thus is not required to hold Ether at all. ==== Security Considerations There are two important considerations concerning the use of `permit`. The first is that a valid permit signature expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be considered as an intention to spend the allowance in any specific way. The second is that because permits have built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be generally recommended is: ```solidity function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} doThing(..., value); } function doThing(..., uint256 value) public { token.safeTransferFrom(msg.sender, address(this), value); ... } ``` Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also {SafeERC20-safeTransferFrom}). Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so contracts should have entry points that don't rely on permit.","kind":"dev","methods":{"DOMAIN_SEPARATOR()":{"details":"Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}."},"nonces(address)":{"details":"Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times."},"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)":{"details":"Sets `value` as the allowance of `spender` over ``owner``'s tokens, given ``owner``'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. CAUTION: See Security Considerations above."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in https://eips.ethereum.org/EIPS/eip-2612[ERC-2612]. Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't need to send a transaction, and thus is not required to hold Ether at all. ==== Security Considerations There are two important considerations concerning the use of `permit`. The first is that a valid permit signature expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be considered as an intention to spend the allowance in any specific way. The second is that because permits have built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be generally recommended is: ```solidity function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} doThing(..., value); } function doThing(..., uint256 value) public { token.safeTransferFrom(msg.sender, address(this), value); ... } ``` Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also {SafeERC20-safeTransferFrom}). Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so contracts should have entry points that don't rely on permit.\",\"kind\":\"dev\",\"methods\":{\"DOMAIN_SEPARATOR()\":{\"details\":\"Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\"},\"nonces(address)\":{\"details\":\"Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times.\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Sets `value` as the allowance of `spender` over ``owner``'s tokens, given ``owner``'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. CAUTION: See Security Considerations above.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"IERC20Permit\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x5838f2ff3b1c4e6b40f973a29cce9f16871bd7a03add5aeeb7f876df39e92167\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://220c9bc7c31596b7d0ad7806037a3ebaed6c271c84df15e3789d850deef3fb1a\",\"dweb:/ipfs/QmU3xjtrAqz9fBLJKHC8Q4LCXpTi77i2oJJbu5Q5Ex2h4J\"]}},\"version\":1}"},"hashes":{"DOMAIN_SEPARATOR()":"3644e515","nonces(address)":"7ecebe00","permit(address,address,uint256,uint256,uint8,bytes32,bytes32)":"d505accf"}},"solidity/FastBridge.sol:IFastBridge":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositRefunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"}],"name":"BridgeProofDisputed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":false,"internalType":"bytes32","name":"transactionHash","type":"bytes32"}],"name":"BridgeProofProvided","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint32","name":"originChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"chainGasAmount","type":"uint256"}],"name":"BridgeRelayed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes","name":"request","type":"bytes"},{"indexed":false,"internalType":"uint32","name":"destChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"sendChainGas","type":"bool"}],"name":"BridgeRequested","type":"event"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstChainId","type":"uint32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IFastBridge.BridgeParams","name":"params","type":"tuple"}],"name":"bridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"address","name":"relayer","type":"address"}],"name":"canClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"address","name":"to","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"dispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"getBridgeTransaction","outputs":[{"components":[{"internalType":"uint32","name":"originChainId","type":"uint32"},{"internalType":"uint32","name":"destChainId","type":"uint32"},{"internalType":"address","name":"originSender","type":"address"},{"internalType":"address","name":"destRecipient","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256","name":"originFeeAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct IFastBridge.BridgeTransaction","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"bytes32","name":"destTxHash","type":"bytes32"}],"name":"prove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"relay","outputs":[],"stateMutability":"payable","type":"function"}],"userDoc":{"kind":"user","methods":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"notice":"Initiates bridge on origin chain to be relayed by off-chain relayer"},"canClaim(bytes32,address)":{"notice":"Checks if the dispute period has passed so bridge deposit can be claimed"},"claim(bytes,address)":{"notice":"Completes bridge transaction on origin chain by claiming originally deposited capital"},"dispute(bytes32)":{"notice":"Disputes an outstanding proof in case relayer provided dest chain tx is invalid"},"getBridgeTransaction(bytes)":{"notice":"Decodes bridge request into a bridge transaction"},"prove(bytes,bytes32)":{"notice":"Provides proof on origin side that relayer provided funds on destination side of bridge transaction"},"refund(bytes)":{"notice":"Refunds an outstanding bridge transaction in case optimistic bridging failed"},"relay(bytes)":{"notice":"Relays destination side of bridge transaction by off-chain relayer"}},"version":1},"developerDoc":{"kind":"dev","methods":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"params":{"params":"The parameters required to bridge"}},"canClaim(bytes32,address)":{"params":{"relayer":"The address of the relayer attempting to claim","transactionId":"The transaction id associated with the encoded bridge transaction to check"}},"claim(bytes,address)":{"params":{"request":"The encoded bridge transaction to claim on origin chain","to":"The recipient address of the funds"}},"dispute(bytes32)":{"params":{"transactionId":"The transaction id associated with the encoded bridge transaction to dispute"}},"getBridgeTransaction(bytes)":{"params":{"request":"The bridge request to decode"}},"prove(bytes,bytes32)":{"params":{"destTxHash":"The destination tx hash proving bridge transaction was relayed","request":"The encoded bridge transaction to prove on origin chain"}},"refund(bytes)":{"params":{"request":"The encoded bridge transaction to refund"}},"relay(bytes)":{"params":{"request":"The encoded bridge transaction to relay on destination chain"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositRefunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"BridgeProofDisputed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"transactionHash\",\"type\":\"bytes32\"}],\"name\":\"BridgeProofProvided\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"BridgeRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"}],\"name\":\"BridgeRequested\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"bridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"canClaim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"dispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"getBridgeTransaction\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originSender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destRecipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originFeeAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeTransaction\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"destTxHash\",\"type\":\"bytes32\"}],\"name\":\"prove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"refund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"params\":{\"params\":\"The parameters required to bridge\"}},\"canClaim(bytes32,address)\":{\"params\":{\"relayer\":\"The address of the relayer attempting to claim\",\"transactionId\":\"The transaction id associated with the encoded bridge transaction to check\"}},\"claim(bytes,address)\":{\"params\":{\"request\":\"The encoded bridge transaction to claim on origin chain\",\"to\":\"The recipient address of the funds\"}},\"dispute(bytes32)\":{\"params\":{\"transactionId\":\"The transaction id associated with the encoded bridge transaction to dispute\"}},\"getBridgeTransaction(bytes)\":{\"params\":{\"request\":\"The bridge request to decode\"}},\"prove(bytes,bytes32)\":{\"params\":{\"destTxHash\":\"The destination tx hash proving bridge transaction was relayed\",\"request\":\"The encoded bridge transaction to prove on origin chain\"}},\"refund(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to refund\"}},\"relay(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to relay on destination chain\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"notice\":\"Initiates bridge on origin chain to be relayed by off-chain relayer\"},\"canClaim(bytes32,address)\":{\"notice\":\"Checks if the dispute period has passed so bridge deposit can be claimed\"},\"claim(bytes,address)\":{\"notice\":\"Completes bridge transaction on origin chain by claiming originally deposited capital\"},\"dispute(bytes32)\":{\"notice\":\"Disputes an outstanding proof in case relayer provided dest chain tx is invalid\"},\"getBridgeTransaction(bytes)\":{\"notice\":\"Decodes bridge request into a bridge transaction\"},\"prove(bytes,bytes32)\":{\"notice\":\"Provides proof on origin side that relayer provided funds on destination side of bridge transaction\"},\"refund(bytes)\":{\"notice\":\"Refunds an outstanding bridge transaction in case optimistic bridging failed\"},\"relay(bytes)\":{\"notice\":\"Relays destination side of bridge transaction by off-chain relayer\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"IFastBridge\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x5838f2ff3b1c4e6b40f973a29cce9f16871bd7a03add5aeeb7f876df39e92167\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://220c9bc7c31596b7d0ad7806037a3ebaed6c271c84df15e3789d850deef3fb1a\",\"dweb:/ipfs/QmU3xjtrAqz9fBLJKHC8Q4LCXpTi77i2oJJbu5Q5Ex2h4J\"]}},\"version\":1}"},"hashes":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":"45851694","canClaim(bytes32,address)":"aa9641ab","claim(bytes,address)":"41fcb612","dispute(bytes32)":"add98c70","getBridgeTransaction(bytes)":"ac11fb1a","prove(bytes,bytes32)":"886d36ff","refund(bytes)":"5eb7d946","relay(bytes)":"8f0d6f17"}},"solidity/FastBridge.sol:SafeERC20":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122005400bbfbb5fd0089c6f9c2d1b90d14696e5ecb30fcae08fe245f0ac1ce92b2564736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122005400bbfbb5fd0089c6f9c2d1b90d14696e5ecb30fcae08fe245f0ac1ce92b2564736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"25597:5019:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;25597:5019:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"25597:5019:0:-:0;;;;;;;;","abiDefinition":[{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"currentAllowance","type":"uint256"},{"internalType":"uint256","name":"requestedDecrease","type":"uint256"}],"name":"SafeERC20FailedDecreaseAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Wrappers around ERC-20 operations that throw on failure (when the token contract returns false). Tokens that return no value (and instead revert or throw on failure) are also supported, non-reverting calls are assumed to be successful. To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, which allows you to call the safe operations as `token.safeTransfer(...)`, etc.","errors":{"SafeERC20FailedDecreaseAllowance(address,uint256,uint256)":[{"details":"Indicates a failed `decreaseAllowance` request."}],"SafeERC20FailedOperation(address)":[{"details":"An operation with an ERC-20 token failed."}]},"kind":"dev","methods":{},"title":"SafeERC20","version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"currentAllowance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestedDecrease\",\"type\":\"uint256\"}],\"name\":\"SafeERC20FailedDecreaseAllowance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"}],\"devdoc\":{\"details\":\"Wrappers around ERC-20 operations that throw on failure (when the token contract returns false). Tokens that return no value (and instead revert or throw on failure) are also supported, non-reverting calls are assumed to be successful. To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\",\"errors\":{\"SafeERC20FailedDecreaseAllowance(address,uint256,uint256)\":[{\"details\":\"Indicates a failed `decreaseAllowance` request.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}]},\"kind\":\"dev\",\"methods\":{},\"title\":\"SafeERC20\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"SafeERC20\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x5838f2ff3b1c4e6b40f973a29cce9f16871bd7a03add5aeeb7f876df39e92167\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://220c9bc7c31596b7d0ad7806037a3ebaed6c271c84df15e3789d850deef3fb1a\",\"dweb:/ipfs/QmU3xjtrAqz9fBLJKHC8Q4LCXpTi77i2oJJbu5Q5Ex2h4J\"]}},\"version\":1}"},"hashes":{}},"solidity/FastBridge.sol:UniversalTokenLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220e0b99ca0473a4b615794462912a21c7b61d5dc8961d7074cb84653b63782c78c64736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220e0b99ca0473a4b615794462912a21c7b61d5dc8961d7074cb84653b63782c78c64736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"37557:2551:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;37557:2551:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"37557:2551:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"UniversalTokenLib\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x5838f2ff3b1c4e6b40f973a29cce9f16871bd7a03add5aeeb7f876df39e92167\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://220c9bc7c31596b7d0ad7806037a3ebaed6c271c84df15e3789d850deef3fb1a\",\"dweb:/ipfs/QmU3xjtrAqz9fBLJKHC8Q4LCXpTi77i2oJJbu5Q5Ex2h4J\"]}},\"version\":1}"},"hashes":{}}} \ No newline at end of file +{"solidity/FastBridge.sol:AccessControl":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Contract module that allows children to implement role-based access control mechanisms. This is a lightweight version that doesn't allow enumerating role members except through off-chain means by accessing the contract event logs. Some applications may benefit from on-chain enumerability, for those cases see {AccessControlEnumerable}. Roles are referred to by their `bytes32` identifier. These should be exposed in the external API and be unique. The best way to achieve this is by using `public constant` hash digests: ```solidity bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\"); ``` Roles can be used to represent a set of permissions. To restrict access to a function call, use {hasRole}: ```solidity function foo() public { require(hasRole(MY_ROLE, msg.sender)); ... } ``` Roles can be granted and revoked dynamically via the {grantRole} and {revokeRole} functions. Each role has an associated admin role, and only accounts that have a role's admin role can call {grantRole} and {revokeRole}. By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using {_setRoleAdmin}. WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} to enforce additional security measures for this role.","errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Contract module that allows children to implement role-based access control mechanisms. This is a lightweight version that doesn't allow enumerating role members except through off-chain means by accessing the contract event logs. Some applications may benefit from on-chain enumerability, for those cases see {AccessControlEnumerable}. Roles are referred to by their `bytes32` identifier. These should be exposed in the external API and be unique. The best way to achieve this is by using `public constant` hash digests: ```solidity bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\"); ``` Roles can be used to represent a set of permissions. To restrict access to a function call, use {hasRole}: ```solidity function foo() public { require(hasRole(MY_ROLE, msg.sender)); ... } ``` Roles can be granted and revoked dynamically via the {grantRole} and {revokeRole} functions. Each role has an associated admin role, and only accounts that have a role's admin role can call {grantRole} and {revokeRole}. By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using {_setRoleAdmin}. WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} to enforce additional security measures for this role.\",\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"AccessControl\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x7da00701c906b2b78d838eb9c510ab5903b6dd7f8e5fb12d4c4710c350e3c919\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://faff50fb8d1f3cf10122c1b611d0987ca58f4099d90c17163816c90d3077bce7\",\"dweb:/ipfs/QmWKF2L9D18J9QXiMbm6ucj3x8ebjQtTrycnkNmB4q3JRo\"]}},\"version\":1}"},"hashes":{"DEFAULT_ADMIN_ROLE()":"a217fddf","getRoleAdmin(bytes32)":"248a9ca3","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","supportsInterface(bytes4)":"01ffc9a7"}},"solidity/FastBridge.sol:AccessControlEnumerable":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Extension of {AccessControl} that allows enumerating the members of each role.","errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"getRoleMember(bytes32,uint256)":{"details":"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information."},"getRoleMemberCount(bytes32)":{"details":"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Extension of {AccessControl} that allows enumerating the members of each role.\",\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"getRoleMember(bytes32,uint256)\":{\"details\":\"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.\"},\"getRoleMemberCount(bytes32)\":{\"details\":\"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"AccessControlEnumerable\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x7da00701c906b2b78d838eb9c510ab5903b6dd7f8e5fb12d4c4710c350e3c919\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://faff50fb8d1f3cf10122c1b611d0987ca58f4099d90c17163816c90d3077bce7\",\"dweb:/ipfs/QmWKF2L9D18J9QXiMbm6ucj3x8ebjQtTrycnkNmB4q3JRo\"]}},\"version\":1}"},"hashes":{"DEFAULT_ADMIN_ROLE()":"a217fddf","getRoleAdmin(bytes32)":"248a9ca3","getRoleMember(bytes32,uint256)":"9010d07c","getRoleMemberCount(bytes32)":"ca15c873","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","supportsInterface(bytes4)":"01ffc9a7"}},"solidity/FastBridge.sol:Address":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220484b80cd78ad146ed37d87f73b71fece9b7aef1b9090eddf52e592358acac67e64736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220484b80cd78ad146ed37d87f73b71fece9b7aef1b9090eddf52e592358acac67e64736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"15602:6066:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;15602:6066:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"15602:6066:0:-:0;;;;;;;;","abiDefinition":[{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Collection of functions related to the address type","errors":{"AddressEmptyCode(address)":[{"details":"There's no code at `target` (it is not a contract)."}],"AddressInsufficientBalance(address)":[{"details":"The ETH balance of the account is not enough to perform the operation."}],"FailedInnerCall()":[{"details":"A call to an address target failed. The target may have reverted."}]},"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"}],\"devdoc\":{\"details\":\"Collection of functions related to the address type\",\"errors\":{\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"AddressInsufficientBalance(address)\":[{\"details\":\"The ETH balance of the account is not enough to perform the operation.\"}],\"FailedInnerCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}]},\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"Address\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x7da00701c906b2b78d838eb9c510ab5903b6dd7f8e5fb12d4c4710c350e3c919\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://faff50fb8d1f3cf10122c1b611d0987ca58f4099d90c17163816c90d3077bce7\",\"dweb:/ipfs/QmWKF2L9D18J9QXiMbm6ucj3x8ebjQtTrycnkNmB4q3JRo\"]}},\"version\":1}"},"hashes":{}},"solidity/FastBridge.sol:Admin":{"code":"0x60806040523480156200001157600080fd5b50604051620014123803806200141283398101604081905262000034916200018e565b6200004160008262000049565b5050620001b9565b60008062000058848462000086565b905080156200007d5760008481526001602052604090206200007b908462000134565b505b90505b92915050565b6000828152602081815260408083206001600160a01b038516845290915281205460ff166200012b576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620000e23390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600162000080565b50600062000080565b60006200007d836001600160a01b03841660008181526001830160205260408120546200012b5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000080565b600060208284031215620001a157600080fd5b81516001600160a01b03811681146200007d57600080fd5b61124980620001c96000396000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806391d14854116100d8578063bf333f2c1161008c578063d547741f11610066578063d547741f14610385578063dcf844a714610398578063e00a83e0146103b857600080fd5b8063bf333f2c14610341578063ca15c8731461034b578063ccc574901461035e57600080fd5b8063a217fddf116100bd578063a217fddf14610313578063b13aa2d61461031b578063b250fe6b1461032e57600080fd5b806391d14854146102a8578063926d7d7f146102ec57600080fd5b80632f2ff15d1161012f57806358f858801161011457806358f85880146102405780635960ccf2146102495780639010d07c1461027057600080fd5b80632f2ff15d1461021a57806336568abe1461022d57600080fd5b806306f333f21161016057806306f333f2146101d95780630f5f6ed7146101ee578063248a9ca3146101f757600080fd5b806301ffc9a71461017c57806303ed0ee5146101a4575b600080fd5b61018f61018a366004611013565b6103c1565b60405190151581526020015b60405180910390f35b6101cb7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b60405190815260200161019b565b6101ec6101e736600461107e565b61041d565b005b6101cb61271081565b6101cb6102053660046110b1565b60009081526020819052604090206001015490565b6101ec6102283660046110ca565b61050b565b6101ec61023b3660046110ca565b610536565b6101cb60025481565b6101cb7fdb9556138406326f00296e13ea2ad7db24ba82381212d816b1a40c23b466b32781565b61028361027e3660046110ed565b61058f565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b61018f6102b63660046110ca565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6101cb7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b6101cb600081565b6101ec6103293660046110b1565b6105ae565b6101ec61033c3660046110b1565b610690565b6101cb620f424081565b6101cb6103593660046110b1565b6106f8565b6101cb7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b6101ec6103933660046110ca565b61070f565b6101cb6103a636600461110f565b60036020526000908152604090205481565b6101cb60045481565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f000000000000000000000000000000000000000000000000000000001480610417575061041782610734565b92915050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55610447816107cb565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120549081900361047b5750505050565b73ffffffffffffffffffffffffffffffffffffffff84166000818152600360205260408120556104ac9084836107d8565b6040805173ffffffffffffffffffffffffffffffffffffffff8087168252851660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b505050565b600082815260208190526040902060010154610526816107cb565b610530838361092f565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610585576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105068282610964565b60008281526001602052604081206105a79083610991565b9392505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556105d8816107cb565b612710821115610649576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064015b60405180910390fd5b600280549083905560408051828152602081018590527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a1505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556106ba816107cb565b600480549083905560408051828152602081018590527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa9101610683565b60008181526001602052604081206104179061099d565b60008281526020819052604090206001015461072a816107cb565b6105308383610964565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061041757507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610417565b6107d581336109a7565b50565b3073ffffffffffffffffffffffffffffffffffffffff8316036107fa57505050565b8060000361080757505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff84160161090e5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461089e576040519150601f19603f3d011682016040523d82523d6000602084013e6108a3565b606091505b5050905080610530576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c6564000000000000000000000000006044820152606401610640565b61050673ffffffffffffffffffffffffffffffffffffffff84168383610a31565b60008061093c8484610abe565b905080156105a757600084815260016020526040902061095c9084610bba565b509392505050565b6000806109718484610bdc565b905080156105a757600084815260016020526040902061095c9084610c97565b60006105a78383610cb9565b6000610417825490565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610a2d576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260248101839052604401610640565b5050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610506908490610ce3565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16610bb25760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610b503390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610417565b506000610417565b60006105a78373ffffffffffffffffffffffffffffffffffffffff8416610d79565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff1615610bb25760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610417565b60006105a78373ffffffffffffffffffffffffffffffffffffffff8416610dc0565b6000826000018281548110610cd057610cd061112a565b9060005260206000200154905092915050565b6000610d0573ffffffffffffffffffffffffffffffffffffffff841683610eb3565b90508051600014158015610d2a575080806020019051810190610d289190611159565b155b15610506576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610640565b6000818152600183016020526040812054610bb257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610417565b60008181526001830160205260408120548015610ea9576000610de460018361117b565b8554909150600090610df89060019061117b565b9050808214610e5d576000866000018281548110610e1857610e1861112a565b9060005260206000200154905080876000018481548110610e3b57610e3b61112a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080610e6e57610e6e6111b5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610417565b6000915050610417565b60606105a783836000846000808573ffffffffffffffffffffffffffffffffffffffff168486604051610ee691906111e4565b60006040518083038185875af1925050503d8060008114610f23576040519150601f19603f3d011682016040523d82523d6000602084013e610f28565b606091505b5091509150610f38868383610f42565b9695505050505050565b606082610f5757610f5282610fd1565b6105a7565b8151158015610f7b575073ffffffffffffffffffffffffffffffffffffffff84163b155b15610fca576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610640565b50806105a7565b805115610fe15780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561102557600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146105a757600080fd5b803573ffffffffffffffffffffffffffffffffffffffff8116811461107957600080fd5b919050565b6000806040838503121561109157600080fd5b61109a83611055565b91506110a860208401611055565b90509250929050565b6000602082840312156110c357600080fd5b5035919050565b600080604083850312156110dd57600080fd5b823591506110a860208401611055565b6000806040838503121561110057600080fd5b50508035926020909101359150565b60006020828403121561112157600080fd5b6105a782611055565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561116b57600080fd5b815180151581146105a757600080fd5b81810381811115610417577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000825160005b8181101561120557602081860181015185830152016111eb565b50600092019182525091905056fea2646970667358221220ae622a2da80c730eb06fbc09f0feabbb824bbdb349894cba40b3bf6d93d73db164736f6c63430008140033","runtime-code":"0x608060405234801561001057600080fd5b50600436106101775760003560e01c806391d14854116100d8578063bf333f2c1161008c578063d547741f11610066578063d547741f14610385578063dcf844a714610398578063e00a83e0146103b857600080fd5b8063bf333f2c14610341578063ca15c8731461034b578063ccc574901461035e57600080fd5b8063a217fddf116100bd578063a217fddf14610313578063b13aa2d61461031b578063b250fe6b1461032e57600080fd5b806391d14854146102a8578063926d7d7f146102ec57600080fd5b80632f2ff15d1161012f57806358f858801161011457806358f85880146102405780635960ccf2146102495780639010d07c1461027057600080fd5b80632f2ff15d1461021a57806336568abe1461022d57600080fd5b806306f333f21161016057806306f333f2146101d95780630f5f6ed7146101ee578063248a9ca3146101f757600080fd5b806301ffc9a71461017c57806303ed0ee5146101a4575b600080fd5b61018f61018a366004611013565b6103c1565b60405190151581526020015b60405180910390f35b6101cb7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b60405190815260200161019b565b6101ec6101e736600461107e565b61041d565b005b6101cb61271081565b6101cb6102053660046110b1565b60009081526020819052604090206001015490565b6101ec6102283660046110ca565b61050b565b6101ec61023b3660046110ca565b610536565b6101cb60025481565b6101cb7fdb9556138406326f00296e13ea2ad7db24ba82381212d816b1a40c23b466b32781565b61028361027e3660046110ed565b61058f565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b61018f6102b63660046110ca565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6101cb7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b6101cb600081565b6101ec6103293660046110b1565b6105ae565b6101ec61033c3660046110b1565b610690565b6101cb620f424081565b6101cb6103593660046110b1565b6106f8565b6101cb7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b6101ec6103933660046110ca565b61070f565b6101cb6103a636600461110f565b60036020526000908152604090205481565b6101cb60045481565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f000000000000000000000000000000000000000000000000000000001480610417575061041782610734565b92915050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55610447816107cb565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120549081900361047b5750505050565b73ffffffffffffffffffffffffffffffffffffffff84166000818152600360205260408120556104ac9084836107d8565b6040805173ffffffffffffffffffffffffffffffffffffffff8087168252851660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b505050565b600082815260208190526040902060010154610526816107cb565b610530838361092f565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610585576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105068282610964565b60008281526001602052604081206105a79083610991565b9392505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556105d8816107cb565b612710821115610649576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064015b60405180910390fd5b600280549083905560408051828152602081018590527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a1505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556106ba816107cb565b600480549083905560408051828152602081018590527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa9101610683565b60008181526001602052604081206104179061099d565b60008281526020819052604090206001015461072a816107cb565b6105308383610964565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061041757507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610417565b6107d581336109a7565b50565b3073ffffffffffffffffffffffffffffffffffffffff8316036107fa57505050565b8060000361080757505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff84160161090e5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461089e576040519150601f19603f3d011682016040523d82523d6000602084013e6108a3565b606091505b5050905080610530576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c6564000000000000000000000000006044820152606401610640565b61050673ffffffffffffffffffffffffffffffffffffffff84168383610a31565b60008061093c8484610abe565b905080156105a757600084815260016020526040902061095c9084610bba565b509392505050565b6000806109718484610bdc565b905080156105a757600084815260016020526040902061095c9084610c97565b60006105a78383610cb9565b6000610417825490565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610a2d576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260248101839052604401610640565b5050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610506908490610ce3565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16610bb25760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610b503390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610417565b506000610417565b60006105a78373ffffffffffffffffffffffffffffffffffffffff8416610d79565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff1615610bb25760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610417565b60006105a78373ffffffffffffffffffffffffffffffffffffffff8416610dc0565b6000826000018281548110610cd057610cd061112a565b9060005260206000200154905092915050565b6000610d0573ffffffffffffffffffffffffffffffffffffffff841683610eb3565b90508051600014158015610d2a575080806020019051810190610d289190611159565b155b15610506576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610640565b6000818152600183016020526040812054610bb257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610417565b60008181526001830160205260408120548015610ea9576000610de460018361117b565b8554909150600090610df89060019061117b565b9050808214610e5d576000866000018281548110610e1857610e1861112a565b9060005260206000200154905080876000018481548110610e3b57610e3b61112a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080610e6e57610e6e6111b5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610417565b6000915050610417565b60606105a783836000846000808573ffffffffffffffffffffffffffffffffffffffff168486604051610ee691906111e4565b60006040518083038185875af1925050503d8060008114610f23576040519150601f19603f3d011682016040523d82523d6000602084013e610f28565b606091505b5091509150610f38868383610f42565b9695505050505050565b606082610f5757610f5282610fd1565b6105a7565b8151158015610f7b575073ffffffffffffffffffffffffffffffffffffffff84163b155b15610fca576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610640565b50806105a7565b805115610fe15780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561102557600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146105a757600080fd5b803573ffffffffffffffffffffffffffffffffffffffff8116811461107957600080fd5b919050565b6000806040838503121561109157600080fd5b61109a83611055565b91506110a860208401611055565b90509250929050565b6000602082840312156110c357600080fd5b5035919050565b600080604083850312156110dd57600080fd5b823591506110a860208401611055565b6000806040838503121561110057600080fd5b50508035926020909101359150565b60006020828403121561112157600080fd5b6105a782611055565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561116b57600080fd5b815180151581146105a757600080fd5b81810381811115610417577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000825160005b8181101561120557602081860181015185830152016111eb565b50600092019182525091905056fea2646970667358221220ae622a2da80c730eb06fbc09f0feabbb824bbdb349894cba40b3bf6d93d73db164736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"56331:1843:0:-:0;;;57158:83;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;57196:38;46368:4;57227:6;57196:10;:38::i;:::-;;57158:83;56331:1843;;55681:257;55767:4;;55798:31;55815:4;55821:7;55798:16;:31::i;:::-;55783:46;;55843:7;55839:69;;;55866:18;;;;:12;:18;;;;;:31;;55889:7;55866:22;:31::i;:::-;;55839:69;55924:7;-1:-1:-1;55681:257:0;;;;;:::o;50315:316::-;50392:4;47090:12;;;;;;;;;;;-1:-1:-1;;;;;47090:29:0;;;;;;;;;;;;50408:217;;50451:6;:12;;;;;;;;;;;-1:-1:-1;;;;;50451:29:0;;;;;;;;;:36;;-1:-1:-1;;50451:36:0;50483:4;50451:36;;;50533:12;22406:10;;22327:96;50533:12;-1:-1:-1;;;;;50506:40:0;50524:7;-1:-1:-1;;;;;50506:40:0;50518:4;50506:40;;;;;;;;;;-1:-1:-1;50567:4:0;50560:11;;50408:217;-1:-1:-1;50609:5:0;50602:12;;31852:150;31922:4;31945:50;31950:3;-1:-1:-1;;;;;31970:23:0;;25840:4;27896:21;;;:14;;;:21;;;;;;25856:321;;-1:-1:-1;25898:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;26080:18;;26056:21;;;:14;;;:21;;;;;;:42;;;;26112:11;;14:290:1;84:6;137:2;125:9;116:7;112:23;108:32;105:52;;;153:1;150;143:12;105:52;179:16;;-1:-1:-1;;;;;224:31:1;;214:42;;204:70;;270:1;267;260:12;14:290;56331:1843:0;;;;;;","srcMapRuntime":"56331:1843:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54341:212;;;;;;:::i;:::-;;:::i;:::-;;;516:14:1;;509:22;491:41;;479:2;464:18;54341:212:0;;;;;;;;56571:60;;56608:23;56571:60;;;;;689:25:1;;;677:2;662:18;56571:60:0;543:177:1;57543:359:0;;;;;;:::i;:::-;;:::i;:::-;;56753:45;;56792:6;56753:45;;47946:120;;;;;;:::i;:::-;48011:7;48037:12;;;;;;;;;;:22;;;;47946:120;48362:136;;;;;;:::i;:::-;;:::i;49464:245::-;;;;;;:::i;:::-;;:::i;56915:30::-;;;;;;56499:66;;56539:26;56499:66;;55138:142;;;;;;:::i;:::-;;:::i;:::-;;;2246:42:1;2234:55;;;2216:74;;2204:2;2189:18;55138:142:0;2070:226:1;46990:136:0;;;;;;:::i;:::-;47067:4;47090:12;;;;;;;;;;;:29;;;;;;;;;;;;;;;;46990:136;56429:64;;56468:25;56429:64;;46323:49;;46368:4;46323:49;;57247:290;;;;;;:::i;:::-;;:::i;57908:264::-;;;;;;:::i;:::-;;:::i;56710:37::-;;56744:3;56710:37;;55448:131;;;;;;:::i;:::-;;:::i;56637:66::-;;56677:26;56637:66;;48778:138;;;;;;:::i;:::-;;:::i;57001:47::-;;;;;;:::i;:::-;;;;;;;;;;;;;;57122:29;;;;;;54341:212;54426:4;54449:57;;;54464:42;54449:57;;:97;;;54510:36;54534:11;54510:23;:36::i;:::-;54442:104;54341:212;-1:-1:-1;;54341:212:0:o;57543:359::-;56677:26;46600:16;46611:4;46600:10;:16::i;:::-;57667:19:::1;::::0;::::1;57647:17;57667:19:::0;;;:12:::1;:19;::::0;;;;;;57700:14;;;57696:27:::1;;57716:7;57543:359:::0;;;:::o;57696:27::-:1;57764:19;::::0;::::1;57786:1;57764:19:::0;;;:12:::1;:19;::::0;;;;:23;57797:45:::1;::::0;57821:9;57832;57797:23:::1;:45::i;:::-;57857:38;::::0;;2889:42:1;2958:15;;;2940:34;;3010:15;;3005:2;2990:18;;2983:43;3042:18;;;3035:34;;;57857:38:0::1;::::0;2867:2:1;2852:18;57857:38:0::1;;;;;;;57637:265;46626:1;57543:359:::0;;;:::o;48362:136::-;48011:7;48037:12;;;;;;;;;;:22;;;46600:16;46611:4;46600:10;:16::i;:::-;48466:25:::1;48477:4;48483:7;48466:10;:25::i;:::-;;48362:136:::0;;;:::o;49464:245::-;49557:34;;;22406:10;49557:34;49553:102;;49614:30;;;;;;;;;;;;;;49553:102;49665:37;49677:4;49683:18;49665:11;:37::i;55138:142::-;55219:7;55245:18;;;:12;:18;;;;;:28;;55267:5;55245:21;:28::i;:::-;55238:35;55138:142;-1:-1:-1;;;55138:142:0:o;57247:290::-;56677:26;46600:16;46611:4;46600:10;:16::i;:::-;56792:6:::1;57346:10;:26;;57338:55;;;::::0;::::1;::::0;;3282:2:1;57338:55:0::1;::::0;::::1;3264:21:1::0;3321:2;3301:18;;;3294:30;3360:18;3340;;;3333:46;3396:18;;57338:55:0::1;;;;;;;;;57424:15;::::0;;57449:28;;;;57492:38:::1;::::0;;3599:25:1;;;3655:2;3640:18;;3633:34;;;57492:38:0::1;::::0;3572:18:1;57492:38:0::1;;;;;;;;57328:209;57247:290:::0;;:::o;57908:264::-;56677:26;46600:16;46611:4;46600:10;:16::i;:::-;58033:14:::1;::::0;;58057:34;;;;58106:59:::1;::::0;;3599:25:1;;;3655:2;3640:18;;3633:34;;;58106:59:0::1;::::0;3572:18:1;58106:59:0::1;3425:248:1::0;55448:131:0;55519:7;55545:18;;;:12;:18;;;;;:27;;:25;:27::i;48778:138::-;48011:7;48037:12;;;;;;;;;;:22;;;46600:16;46611:4;46600:10;:16::i;:::-;48883:26:::1;48895:4;48901:7;48883:11;:26::i;46701:202::-:0;46786:4;46809:47;;;46824:32;46809:47;;:87;;-1:-1:-1;38614:25:0;38599:40;;;;46860:36;38500:146;47335:103;47401:30;47412:4;22406:10;47401;:30::i;:::-;47335:103;:::o;51613:653::-;51788:4;51774:19;;;;51770:32;;51613:653;;;:::o;51770:32::-;51874:5;51883:1;51874:10;51870:23;;51613:653;;;:::o;51870:23::-;51906:20;;;;;51902:358;;52086:12;52103:2;:7;;52118:5;52103:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52085:43;;;52150:7;52142:39;;;;;;;4090:2:1;52142:39:0;;;4072:21:1;4129:2;4109:18;;;4102:30;4168:21;4148:18;;;4141:49;4207:18;;52142:39:0;3888:343:1;51902:358:0;52212:37;:26;;;52239:2;52243:5;52212:26;:37::i;55681:257::-;55767:4;55783:12;55798:31;55815:4;55821:7;55798:16;:31::i;:::-;55783:46;;55843:7;55839:69;;;55866:18;;;;:12;:18;;;;;:31;;55889:7;55866:22;:31::i;:::-;;55924:7;55681:257;-1:-1:-1;;;55681:257:0:o;56041:262::-;56128:4;56144:12;56159:32;56177:4;56183:7;56159:17;:32::i;:::-;56144:47;;56205:7;56201:72;;;56228:18;;;;:12;:18;;;;;:34;;56254:7;56228:25;:34::i;33110:156::-;33184:7;33234:22;33238:3;33250:5;33234:3;:22::i;32653:115::-;32716:7;32742:19;32750:3;28092:18;;28010:107;47568:197;47067:4;47090:12;;;;;;;;;;;:29;;;;;;;;;;;;;47651:108;;47701:47;;;;;4440:42:1;4428:55;;47701:47:0;;;4410:74:1;4500:18;;;4493:34;;;4383:18;;47701:47:0;4236:297:1;47651:108:0;47568:197;;:::o;39818:160::-;39927:43;;;39942:14;4428:55:1;;39927:43:0;;;4410:74:1;4500:18;;;;4493:34;;;39927:43:0;;;;;;;;;;4383:18:1;;;;39927:43:0;;;;;;;;;;;;;;39900:71;;39920:5;;39900:19;:71::i;50315:316::-;50392:4;47090:12;;;;;;;;;;;:29;;;;;;;;;;;;;50408:217;;50451:6;:12;;;;;;;;;;;:29;;;;;;;;;;:36;;;;50483:4;50451:36;;;50533:12;22406:10;;22327:96;50533:12;50506:40;;50524:7;50506:40;;50518:4;50506:40;;;;;;;;;;-1:-1:-1;50567:4:0;50560:11;;50408:217;-1:-1:-1;50609:5:0;50602:12;;31852:150;31922:4;31945:50;31950:3;31970:23;;;31945:4;:50::i;50866:317::-;50944:4;47090:12;;;;;;;;;;;:29;;;;;;;;;;;;;50960:217;;;51034:5;51002:12;;;;;;;;;;;:29;;;;;;;;;;;:37;;;;;;51058:40;22406:10;;51002:12;;51058:40;;51034:5;51058:40;-1:-1:-1;51119:4:0;51112:11;;32170:156;32243:4;32266:53;32274:3;32294:23;;;32266:7;:53::i;28459:118::-;28526:7;28552:3;:11;;28564:5;28552:18;;;;;;;;:::i;:::-;;;;;;;;;28545:25;;28459:118;;;;:::o;42574:629::-;42993:23;43019:33;:27;;;43047:4;43019:27;:33::i;:::-;42993:59;;43066:10;:17;43087:1;43066:22;;:57;;;;;43104:10;43093:30;;;;;;;;;;;;:::i;:::-;43092:31;43066:57;43062:135;;;43146:40;;;;;2246:42:1;2234:55;;43146:40:0;;;2216:74:1;2189:18;;43146:40:0;2070:226:1;25777:406:0;25840:4;27896:21;;;:14;;;:21;;;;;;25856:321;;-1:-1:-1;25898:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;26080:18;;26056:21;;;:14;;;:21;;;;;;:42;;;;26112:11;;26351:1368;26417:4;26546:21;;;:14;;;:21;;;;;;26582:13;;26578:1135;;26949:18;26970:12;26981:1;26970:8;:12;:::i;:::-;27016:18;;26949:33;;-1:-1:-1;26996:17:0;;27016:22;;27037:1;;27016:22;:::i;:::-;26996:42;;27071:9;27057:10;:23;27053:378;;27100:17;27120:3;:11;;27132:9;27120:22;;;;;;;;:::i;:::-;;;;;;;;;27100:42;;27267:9;27241:3;:11;;27253:10;27241:23;;;;;;;;:::i;:::-;;;;;;;;;;;;:35;;;;27380:25;;;:14;;;:25;;;;;:36;;;27053:378;27509:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;27612:3;:14;;:21;27627:5;27612:21;;;;;;;;;;;27605:28;;;27655:4;27648:11;;;;;;;26578:1135;27697:5;27690:12;;;;;18112:151;18187:12;18218:38;18240:6;18248:4;18254:1;18187:12;18828;18842:23;18869:6;:11;;18888:5;18895:4;18869:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18827:73;;;;18917:55;18944:6;18952:7;18961:10;18917:26;:55::i;:::-;18910:62;18587:392;-1:-1:-1;;;;;;18587:392:0:o;20032:582::-;20176:12;20205:7;20200:408;;20228:19;20236:10;20228:7;:19::i;:::-;20200:408;;;20452:17;;:22;:49;;;;-1:-1:-1;20478:18:0;;;;:23;20452:49;20448:119;;;20528:24;;;;;2246:42:1;2234:55;;20528:24:0;;;2216:74:1;2189:18;;20528:24:0;2070:226:1;20448:119:0;-1:-1:-1;20587:10:0;20580:17;;21150:516;21281:17;;:21;21277:383;;21509:10;21503:17;21565:15;21552:10;21548:2;21544:19;21537:44;21277:383;21632:17;;;;;;;;;;;;;;14:332:1;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;180:9;167:23;230:66;223:5;219:78;212:5;209:89;199:117;;312:1;309;302:12;725:196;793:20;;853:42;842:54;;832:65;;822:93;;911:1;908;901:12;822:93;725:196;;;:::o;926:260::-;994:6;1002;1055:2;1043:9;1034:7;1030:23;1026:32;1023:52;;;1071:1;1068;1061:12;1023:52;1094:29;1113:9;1094:29;:::i;:::-;1084:39;;1142:38;1176:2;1165:9;1161:18;1142:38;:::i;:::-;1132:48;;926:260;;;;;:::o;1373:180::-;1432:6;1485:2;1473:9;1464:7;1460:23;1456:32;1453:52;;;1501:1;1498;1491:12;1453:52;-1:-1:-1;1524:23:1;;1373:180;-1:-1:-1;1373:180:1:o;1558:254::-;1626:6;1634;1687:2;1675:9;1666:7;1662:23;1658:32;1655:52;;;1703:1;1700;1693:12;1655:52;1739:9;1726:23;1716:33;;1768:38;1802:2;1791:9;1787:18;1768:38;:::i;1817:248::-;1885:6;1893;1946:2;1934:9;1925:7;1921:23;1917:32;1914:52;;;1962:1;1959;1952:12;1914:52;-1:-1:-1;;1985:23:1;;;2055:2;2040:18;;;2027:32;;-1:-1:-1;1817:248:1:o;2486:186::-;2545:6;2598:2;2586:9;2577:7;2573:23;2569:32;2566:52;;;2614:1;2611;2604:12;2566:52;2637:29;2656:9;2637:29;:::i;4840:184::-;4892:77;4889:1;4882:88;4989:4;4986:1;4979:15;5013:4;5010:1;5003:15;5029:277;5096:6;5149:2;5137:9;5128:7;5124:23;5120:32;5117:52;;;5165:1;5162;5155:12;5117:52;5197:9;5191:16;5250:5;5243:13;5236:21;5229:5;5226:32;5216:60;;5272:1;5269;5262:12;5311:282;5378:9;;;5399:11;;;5396:191;;;5443:77;5440:1;5433:88;5544:4;5541:1;5534:15;5572:4;5569:1;5562:15;5598:184;5650:77;5647:1;5640:88;5747:4;5744:1;5737:15;5771:4;5768:1;5761:15;5787:412;5916:3;5954:6;5948:13;5979:1;5989:129;6003:6;6000:1;5997:13;5989:129;;;6101:4;6085:14;;;6081:25;;6075:32;6062:11;;;6055:53;6018:12;5989:129;;;-1:-1:-1;6173:1:1;6137:16;;6162:13;;;-1:-1:-1;6137:16:1;5787:412;-1:-1:-1;5787:412:1:o","abiDefinition":[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldChainGasAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"ChainGasAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFeeRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"FeeRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesSwept","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_RATE_MAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GOVERNOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GUARD_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFUNDER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAYER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainGasAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"protocolFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"setChainGasAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"setProtocolFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"sweepProtocolFees","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"chainGasAmount()":{"notice":"Chain gas amount to forward as rebate if requested"},"protocolFeeRate()":{"notice":"Protocol fee rate taken on origin amount deposited in origin chain"},"protocolFees(address)":{"notice":"Protocol fee amounts accumulated"}},"version":1},"developerDoc":{"errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}],"AddressEmptyCode(address)":[{"details":"There's no code at `target` (it is not a contract)."}],"AddressInsufficientBalance(address)":[{"details":"The ETH balance of the account is not enough to perform the operation."}],"FailedInnerCall()":[{"details":"A call to an address target failed. The target may have reverted."}],"SafeERC20FailedOperation(address)":[{"details":"An operation with an ERC-20 token failed."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"getRoleMember(bytes32,uint256)":{"details":"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information."},"getRoleMemberCount(bytes32)":{"details":"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REFUNDER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}],\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"AddressInsufficientBalance(address)\":[{\"details\":\"The ETH balance of the account is not enough to perform the operation.\"}],\"FailedInnerCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"getRoleMember(bytes32,uint256)\":{\"details\":\"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.\"},\"getRoleMemberCount(bytes32)\":{\"details\":\"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"chainGasAmount()\":{\"notice\":\"Chain gas amount to forward as rebate if requested\"},\"protocolFeeRate()\":{\"notice\":\"Protocol fee rate taken on origin amount deposited in origin chain\"},\"protocolFees(address)\":{\"notice\":\"Protocol fee amounts accumulated\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"Admin\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x7da00701c906b2b78d838eb9c510ab5903b6dd7f8e5fb12d4c4710c350e3c919\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://faff50fb8d1f3cf10122c1b611d0987ca58f4099d90c17163816c90d3077bce7\",\"dweb:/ipfs/QmWKF2L9D18J9QXiMbm6ucj3x8ebjQtTrycnkNmB4q3JRo\"]}},\"version\":1}"},"hashes":{"DEFAULT_ADMIN_ROLE()":"a217fddf","FEE_BPS()":"bf333f2c","FEE_RATE_MAX()":"0f5f6ed7","GOVERNOR_ROLE()":"ccc57490","GUARD_ROLE()":"03ed0ee5","REFUNDER_ROLE()":"5960ccf2","RELAYER_ROLE()":"926d7d7f","chainGasAmount()":"e00a83e0","getRoleAdmin(bytes32)":"248a9ca3","getRoleMember(bytes32,uint256)":"9010d07c","getRoleMemberCount(bytes32)":"ca15c873","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","protocolFeeRate()":"58f85880","protocolFees(address)":"dcf844a7","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","setChainGasAmount(uint256)":"b250fe6b","setProtocolFeeRate(uint256)":"b13aa2d6","supportsInterface(bytes4)":"01ffc9a7","sweepProtocolFees(address,address)":"06f333f2"}},"solidity/FastBridge.sol:Context":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.","kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"details\":\"Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"Context\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x7da00701c906b2b78d838eb9c510ab5903b6dd7f8e5fb12d4c4710c350e3c919\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://faff50fb8d1f3cf10122c1b611d0987ca58f4099d90c17163816c90d3077bce7\",\"dweb:/ipfs/QmWKF2L9D18J9QXiMbm6ucj3x8ebjQtTrycnkNmB4q3JRo\"]}},\"version\":1}"},"hashes":{}},"solidity/FastBridge.sol:ERC165":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Implementation of the {IERC165} interface. Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check for the additional interface id that will be supported. For example: ```solidity function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); } ```","kind":"dev","methods":{"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Implementation of the {IERC165} interface. Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check for the additional interface id that will be supported. For example: ```solidity function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); } ```\",\"kind\":\"dev\",\"methods\":{\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"ERC165\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x7da00701c906b2b78d838eb9c510ab5903b6dd7f8e5fb12d4c4710c350e3c919\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://faff50fb8d1f3cf10122c1b611d0987ca58f4099d90c17163816c90d3077bce7\",\"dweb:/ipfs/QmWKF2L9D18J9QXiMbm6ucj3x8ebjQtTrycnkNmB4q3JRo\"]}},\"version\":1}"},"hashes":{"supportsInterface(bytes4)":"01ffc9a7"}},"solidity/FastBridge.sol:EnumerableSet":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220ccb9bee87c33656dd99a59e58a032b4a522fa9282d7547294079dc934f18ba3f64736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220ccb9bee87c33656dd99a59e58a032b4a522fa9282d7547294079dc934f18ba3f64736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"24866:11640:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;24866:11640:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"24866:11640:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Library for managing https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive types. Sets have the following properties: - Elements are added, removed, and checked for existence in constant time (O(1)). - Elements are enumerated in O(n). No guarantees are made on the ordering. ```solidity contract Example { // Add the library methods using EnumerableSet for EnumerableSet.AddressSet; // Declare a set state variable EnumerableSet.AddressSet private mySet; } ``` As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) and `uint256` (`UintSet`) are supported. [WARNING] ==== Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. ====","kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"details\":\"Library for managing https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive types. Sets have the following properties: - Elements are added, removed, and checked for existence in constant time (O(1)). - Elements are enumerated in O(n). No guarantees are made on the ordering. ```solidity contract Example { // Add the library methods using EnumerableSet for EnumerableSet.AddressSet; // Declare a set state variable EnumerableSet.AddressSet private mySet; } ``` As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) and `uint256` (`UintSet`) are supported. [WARNING] ==== Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. ====\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"EnumerableSet\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x7da00701c906b2b78d838eb9c510ab5903b6dd7f8e5fb12d4c4710c350e3c919\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://faff50fb8d1f3cf10122c1b611d0987ca58f4099d90c17163816c90d3077bce7\",\"dweb:/ipfs/QmWKF2L9D18J9QXiMbm6ucj3x8ebjQtTrycnkNmB4q3JRo\"]}},\"version\":1}"},"hashes":{}},"solidity/FastBridge.sol:FastBridge":{"code":"0x60a06040523480156200001157600080fd5b5060405162002d7a38038062002d7a833981016040819052620000349162000194565b80620000426000826200004f565b50504360805250620001bf565b6000806200005e84846200008c565b90508015620000835760008481526001602052604090206200008190846200013a565b505b90505b92915050565b6000828152602081815260408083206001600160a01b038516845290915281205460ff1662000131576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620000e83390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600162000086565b50600062000086565b600062000083836001600160a01b0384166000818152600183016020526040812054620001315750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000086565b600060208284031215620001a757600080fd5b81516001600160a01b03811681146200008357600080fd5b608051612b9f620001db60003960006106510152612b9f6000f3fe60806040526004361061026a5760003560e01c80639010d07c11610153578063add98c70116100cb578063ca15c8731161007f578063d547741f11610064578063d547741f146107a1578063dcf844a7146107c1578063e00a83e0146107ee57600080fd5b8063ca15c8731461074d578063ccc574901461076d57600080fd5b8063b13aa2d6116100b0578063b13aa2d6146106f6578063b250fe6b14610716578063bf333f2c1461073657600080fd5b8063add98c70146106c0578063affed0e0146106e057600080fd5b8063a217fddf11610122578063a5bbe22b11610107578063a5bbe22b1461047f578063aa9641ab14610673578063ac11fb1a1461069357600080fd5b8063a217fddf1461062a578063a3ec191a1461063f57600080fd5b80639010d07c146104f857806391ad50391461053057806391d14854146105b2578063926d7d7f146105f657600080fd5b806341fcb612116101e65780635eb7d946116101b55780638379a24f1161019a5780638379a24f14610495578063886d36ff146104c55780638f0d6f17146104e557600080fd5b80635eb7d9461461045f578063820688d51461047f57600080fd5b806341fcb612146103e2578063458516941461040257806358f85880146104155780635960ccf21461042b57600080fd5b80630f5f6ed71161023d578063248a9ca311610222578063248a9ca3146103725780632f2ff15d146103a257806336568abe146103c257600080fd5b80630f5f6ed714610345578063190da5951461035b57600080fd5b806301ffc9a71461026f57806303ed0ee5146102a4578063051287bc146102e657806306f333f214610323575b600080fd5b34801561027b57600080fd5b5061028f61028a3660046122fc565b610804565b60405190151581526020015b60405180910390f35b3480156102b057600080fd5b506102d87f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b60405190815260200161029b565b3480156102f257600080fd5b5061031661030136600461233e565b60056020526000908152604090205460ff1681565b60405161029b9190612386565b34801561032f57600080fd5b5061034361033e3660046123ec565b610860565b005b34801561035157600080fd5b506102d861271081565b34801561036757600080fd5b506102d862093a8081565b34801561037e57600080fd5b506102d861038d36600461233e565b60009081526020819052604090206001015490565b3480156103ae57600080fd5b506103436103bd366004612425565b610927565b3480156103ce57600080fd5b506103436103dd366004612425565b610952565b3480156103ee57600080fd5b506103436103fd366004612572565b61099e565b6103436104103660046125ef565b610bd7565b34801561042157600080fd5b506102d860025481565b34801561043757600080fd5b506102d87fdb9556138406326f00296e13ea2ad7db24ba82381212d816b1a40c23b466b32781565b34801561046b57600080fd5b5061034361047a366004612692565b610ee5565b34801561048b57600080fd5b506102d861070881565b3480156104a157600080fd5b5061028f6104b036600461233e565b60076020526000908152604090205460ff1681565b3480156104d157600080fd5b506103436104e03660046126cf565b6110bd565b6103436104f3366004612692565b6111f0565b34801561050457600080fd5b50610518610513366004612714565b611437565b6040516001600160a01b03909116815260200161029b565b34801561053c57600080fd5b5061058661054b36600461233e565b6006602052600090815260409020546bffffffffffffffffffffffff8116906c0100000000000000000000000090046001600160a01b031682565b604080516bffffffffffffffffffffffff90931683526001600160a01b0390911660208301520161029b565b3480156105be57600080fd5b5061028f6105cd366004612425565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561060257600080fd5b506102d87fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b34801561063657600080fd5b506102d8600081565b34801561064b57600080fd5b506102d87f000000000000000000000000000000000000000000000000000000000000000081565b34801561067f57600080fd5b5061028f61068e366004612425565b611456565b34801561069f57600080fd5b506106b36106ae366004612692565b611559565b60405161029b9190612736565b3480156106cc57600080fd5b506103436106db36600461233e565b6115cc565b3480156106ec57600080fd5b506102d860085481565b34801561070257600080fd5b5061034361071136600461233e565b611735565b34801561072257600080fd5b5061034361073136600461233e565b611817565b34801561074257600080fd5b506102d8620f424081565b34801561075957600080fd5b506102d861076836600461233e565b61187f565b34801561077957600080fd5b506102d87f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b3480156107ad57600080fd5b506103436107bc366004612425565b611896565b3480156107cd57600080fd5b506102d86107dc36600461281c565b60036020526000908152604090205481565b3480156107fa57600080fd5b506102d860045481565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f00000000000000000000000000000000000000000000000000000000148061085a575061085a826118bb565b92915050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561088a81611952565b6001600160a01b038316600090815260036020526040812054908190036108b15750505050565b6001600160a01b0384166000818152600360205260408120556108d590848361195f565b604080516001600160a01b038087168252851660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b505050565b60008281526020819052604090206001015461094281611952565b61094c8383611a82565b50505050565b6001600160a01b0381163314610994576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109228282611ab7565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc46109c881611952565b8251602084012060006109da85611559565b9050600260008381526005602052604090205460ff166004811115610a0157610a01612357565b14610a38576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660209081526040918290208251808401909352546bffffffffffffffffffffffff811683526c0100000000000000000000000090046001600160a01b03169082018190523314610abb576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611610b08576040517f1992d0bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600560205260409020805460ff1916600317905561010082015115610b645761010082015160808301516001600160a01b031660009081526003602052604081208054909190610b5e908490612868565b90915550505b608082015160c0830151610b826001600160a01b038316888361195f565b604080516001600160a01b03848116825260208201849052891691339188917f582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac67891015b60405180910390a45050505050505050565b46816000015163ffffffff1603610c1a576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a08101511580610c2d575060c0810151155b15610c64576040517fe38820c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608101516001600160a01b03161580610c89575060808101516001600160a01b0316155b15610cc0576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ccc61070842612868565b8161010001511015610d0a576040517f04b7fcc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d1f3083606001518460a00151611ae4565b90506000806002541115610d4c57620f424060025483610d3f919061287b565b610d499190612892565b90505b610d5681836128cd565b915060006040518061018001604052804663ffffffff168152602001856000015163ffffffff16815260200185602001516001600160a01b0316815260200185604001516001600160a01b0316815260200185606001516001600160a01b0316815260200185608001516001600160a01b031681526020018481526020018560c0015181526020018381526020018560e0015115158152602001856101000151815260200160086000815480929190610e0e906128e0565b909155509052604051610e249190602001612736565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152828252805160208083019190912060008181526005835293909320805460ff191660011790558701518751606089015160808a015160c08b015160e08c015195985095966001600160a01b039094169587957f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a95610ed6958b959094909390928e9261293c565b60405180910390a35050505050565b805160208201206000610ef783611559565b3360009081527fd2043bf65931af3dbecf60d0db8f40e4160406d7beb00522f4200cf4944a1eb8602052604090205490915060ff1615610f74578061014001514211610f6f576040517fe15ff9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fc0565b62093a80816101400151610f889190612868565b4211610fc0576040517fe15ff9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008381526005602052604090205460ff166004811115610fe557610fe5612357565b1461101c576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260056020526040808220805460ff19166004179055820151608083015161010084015160c0850151929391926110579190612868565b905061106d6001600160a01b038316848361195f565b604080516001600160a01b0384811682526020820184905285169187917fb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958910160405180910390a3505050505050565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc46110e781611952565b82516020840120600160008281526005602052604090205460ff16600481111561111357611113612357565b1461114a576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526005602090815260408083208054600260ff19909116179055805180820182526bffffffffffffffffffffffff4281168252338285018181528787526006865295849020925195516001600160a01b03166c0100000000000000000000000002959091169490941790555185815283917f4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4910160405180910390a350505050565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc461121a81611952565b81516020830120600061122c84611559565b90504663ffffffff16816020015163ffffffff1614611277576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8061014001514211156112b6576040517f559895a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526007602052604090205460ff16156112ff576040517fbef7bb7d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600760205260409020805460ff19166001179055606081015160a082015160e083015160045461012085015161134857506000611342848484611ae4565b506113b9565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b0384160161138c5761134284846113878486612868565b611ae4565b611397848484611ae4565b506113b78473eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee83611ae4565b505b845160808087015160a08089015160c0808b015160e08c01516040805163ffffffff90991689526001600160a01b0396871660208a0152938616938801939093526060870152938501528301849052861691339189917ff8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c9101610bc5565b600082815260016020526040812061144f9083611cb3565b9392505050565b6000600260008481526005602052604090205460ff16600481111561147d5761147d612357565b146114b4576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600660209081526040918290208251808401909352546bffffffffffffffffffffffff811683526001600160a01b036c01000000000000000000000000909104811691830182905284161461153a576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611949350505050565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201528251909161085a91840181019084016129ed565b7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d6115f681611952565b600260008381526005602052604090205460ff16600481111561161b5761161b612357565b14611652576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660209081526040918290208251808401909352546bffffffffffffffffffffffff8082168085526c010000000000000000000000009092046001600160a01b031693909201929092526107089142031611156116e1576040517f3e908aac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040808320805460ff19166001179055600690915280822082905551339184917f0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad49190a35050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561175f81611952565b6127108211156117d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064015b60405180910390fd5b600280549083905560408051828152602081018590527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a1505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561184181611952565b600480549083905560408051828152602081018590527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa910161180a565b600081815260016020526040812061085a90611cbf565b6000828152602081905260409020600101546118b181611952565b61094c8383611ab7565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061085a57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461085a565b61195c8133611cc9565b50565b306001600160a01b0383160361197457505050565b8060000361198157505050565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03841601611a6e576000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146119fe576040519150601f19603f3d011682016040523d82523d6000602084013e611a03565b606091505b505090508061094c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c65640000000000000000000000000060448201526064016117c7565b6109226001600160a01b0384168383611d39565b600080611a8f8484611dad565b9050801561144f576000848152600160205260409020611aaf9084611e57565b509392505050565b600080611ac48484611e6c565b9050801561144f576000848152600160205260409020611aaf9084611eef565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611c4d57611b1c836001600160a01b0316611f04565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528416906370a0823190602401602060405180830381865afa158015611b7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9f9190612ab9565b9050611bb66001600160a01b038416338685611faa565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528291908516906370a0823190602401602060405180830381865afa158015611c18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c3c9190612ab9565b611c4691906128cd565b905061144f565b348214611c86576040517f81de0bf300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0384163014611caa57611caa6001600160a01b038416858461195f565b50349392505050565b600061144f8383611fe3565b600061085a825490565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16611d35576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602481018390526044016117c7565b5050565b6040516001600160a01b0383811660248301526044820183905261092291859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061200d565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16611e4f576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055611e073390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161085a565b50600061085a565b600061144f836001600160a01b038416612089565b6000828152602081815260408083206001600160a01b038516845290915281205460ff1615611e4f576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161085a565b600061144f836001600160a01b0384166120d0565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03821601611f66576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03163b60000361195c576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b03848116602483015283811660448301526064820183905261094c9186918216906323b872dd90608401611d66565b6000826000018281548110611ffa57611ffa612ad2565b9060005260206000200154905092915050565b60006120226001600160a01b038416836121c3565b905080516000141580156120475750808060200190518101906120459190612b01565b155b15610922576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024016117c7565b6000818152600183016020526040812054611e4f5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561085a565b600081815260018301602052604081205480156121b95760006120f46001836128cd565b8554909150600090612108906001906128cd565b905080821461216d57600086600001828154811061212857612128612ad2565b906000526020600020015490508087600001848154811061214b5761214b612ad2565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061217e5761217e612b1e565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061085a565b600091505061085a565b606061144f8383600084600080856001600160a01b031684866040516121e99190612b4d565b60006040518083038185875af1925050503d8060008114612226576040519150601f19603f3d011682016040523d82523d6000602084013e61222b565b606091505b509150915061223b868383612245565b9695505050505050565b60608261225a57612255826122ba565b61144f565b815115801561227157506001600160a01b0384163b155b156122b3576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016117c7565b508061144f565b8051156122ca5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561230e57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461144f57600080fd5b60006020828403121561235057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600583106123c1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6001600160a01b038116811461195c57600080fd5b80356123e7816123c7565b919050565b600080604083850312156123ff57600080fd5b823561240a816123c7565b9150602083013561241a816123c7565b809150509250929050565b6000806040838503121561243857600080fd5b82359150602083013561241a816123c7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171561249d5761249d61244a565b60405290565b604051610180810167ffffffffffffffff8111828210171561249d5761249d61244a565b600082601f8301126124d857600080fd5b813567ffffffffffffffff808211156124f3576124f361244a565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156125395761253961244a565b8160405283815286602085880101111561255257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806040838503121561258557600080fd5b823567ffffffffffffffff81111561259c57600080fd5b6125a8858286016124c7565b925050602083013561241a816123c7565b63ffffffff8116811461195c57600080fd5b80356123e7816125b9565b801515811461195c57600080fd5b80356123e7816125d6565b6000610120828403121561260257600080fd5b61260a612479565b612613836125cb565b8152612621602084016123dc565b6020820152612632604084016123dc565b6040820152612643606084016123dc565b6060820152612654608084016123dc565b608082015260a083013560a082015260c083013560c082015261267960e084016125e4565b60e0820152610100928301359281019290925250919050565b6000602082840312156126a457600080fd5b813567ffffffffffffffff8111156126bb57600080fd5b6126c7848285016124c7565b949350505050565b600080604083850312156126e257600080fd5b823567ffffffffffffffff8111156126f957600080fd5b612705858286016124c7565b95602094909401359450505050565b6000806040838503121561272757600080fd5b50508035926020909101359150565b815163ffffffff1681526101808101602083015161275c602084018263ffffffff169052565b50604083015161277760408401826001600160a01b03169052565b50606083015161279260608401826001600160a01b03169052565b5060808301516127ad60808401826001600160a01b03169052565b5060a08301516127c860a08401826001600160a01b03169052565b5060c083015160c083015260e083015160e0830152610100808401518184015250610120808401516127fd8285018215159052565b5050610140838101519083015261016092830151929091019190915290565b60006020828403121561282e57600080fd5b813561144f816123c7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561085a5761085a612839565b808202811582820484141761085a5761085a612839565b6000826128c8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561085a5761085a612839565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361291157612911612839565b5060010190565b60005b8381101561293357818101518382015260200161291b565b50506000910152565b60e08152600088518060e084015261010061295d8282860160208e01612918565b63ffffffff9990991660208401526001600160a01b039788166040840152959096166060820152608081019390935260a0830191909152151560c0820152601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190910192915050565b80516123e7816125b9565b80516123e7816123c7565b80516123e7816125d6565b60006101808284031215612a0057600080fd5b612a086124a3565b612a11836129cc565b8152612a1f602084016129cc565b6020820152612a30604084016129d7565b6040820152612a41606084016129d7565b6060820152612a52608084016129d7565b6080820152612a6360a084016129d7565b60a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120612a968185016129e2565b908201526101408381015190820152610160928301519281019290925250919050565b600060208284031215612acb57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215612b1357600080fd5b815161144f816125d6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612b5f818460208701612918565b919091019291505056fea26469706673582212207d038d8dfad42c58e5149b646b9e05914f990dd941b51e06388a96d1ed46308264736f6c63430008140033","runtime-code":"0x60806040526004361061026a5760003560e01c80639010d07c11610153578063add98c70116100cb578063ca15c8731161007f578063d547741f11610064578063d547741f146107a1578063dcf844a7146107c1578063e00a83e0146107ee57600080fd5b8063ca15c8731461074d578063ccc574901461076d57600080fd5b8063b13aa2d6116100b0578063b13aa2d6146106f6578063b250fe6b14610716578063bf333f2c1461073657600080fd5b8063add98c70146106c0578063affed0e0146106e057600080fd5b8063a217fddf11610122578063a5bbe22b11610107578063a5bbe22b1461047f578063aa9641ab14610673578063ac11fb1a1461069357600080fd5b8063a217fddf1461062a578063a3ec191a1461063f57600080fd5b80639010d07c146104f857806391ad50391461053057806391d14854146105b2578063926d7d7f146105f657600080fd5b806341fcb612116101e65780635eb7d946116101b55780638379a24f1161019a5780638379a24f14610495578063886d36ff146104c55780638f0d6f17146104e557600080fd5b80635eb7d9461461045f578063820688d51461047f57600080fd5b806341fcb612146103e2578063458516941461040257806358f85880146104155780635960ccf21461042b57600080fd5b80630f5f6ed71161023d578063248a9ca311610222578063248a9ca3146103725780632f2ff15d146103a257806336568abe146103c257600080fd5b80630f5f6ed714610345578063190da5951461035b57600080fd5b806301ffc9a71461026f57806303ed0ee5146102a4578063051287bc146102e657806306f333f214610323575b600080fd5b34801561027b57600080fd5b5061028f61028a3660046122fc565b610804565b60405190151581526020015b60405180910390f35b3480156102b057600080fd5b506102d87f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b60405190815260200161029b565b3480156102f257600080fd5b5061031661030136600461233e565b60056020526000908152604090205460ff1681565b60405161029b9190612386565b34801561032f57600080fd5b5061034361033e3660046123ec565b610860565b005b34801561035157600080fd5b506102d861271081565b34801561036757600080fd5b506102d862093a8081565b34801561037e57600080fd5b506102d861038d36600461233e565b60009081526020819052604090206001015490565b3480156103ae57600080fd5b506103436103bd366004612425565b610927565b3480156103ce57600080fd5b506103436103dd366004612425565b610952565b3480156103ee57600080fd5b506103436103fd366004612572565b61099e565b6103436104103660046125ef565b610bd7565b34801561042157600080fd5b506102d860025481565b34801561043757600080fd5b506102d87fdb9556138406326f00296e13ea2ad7db24ba82381212d816b1a40c23b466b32781565b34801561046b57600080fd5b5061034361047a366004612692565b610ee5565b34801561048b57600080fd5b506102d861070881565b3480156104a157600080fd5b5061028f6104b036600461233e565b60076020526000908152604090205460ff1681565b3480156104d157600080fd5b506103436104e03660046126cf565b6110bd565b6103436104f3366004612692565b6111f0565b34801561050457600080fd5b50610518610513366004612714565b611437565b6040516001600160a01b03909116815260200161029b565b34801561053c57600080fd5b5061058661054b36600461233e565b6006602052600090815260409020546bffffffffffffffffffffffff8116906c0100000000000000000000000090046001600160a01b031682565b604080516bffffffffffffffffffffffff90931683526001600160a01b0390911660208301520161029b565b3480156105be57600080fd5b5061028f6105cd366004612425565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561060257600080fd5b506102d87fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b34801561063657600080fd5b506102d8600081565b34801561064b57600080fd5b506102d87f000000000000000000000000000000000000000000000000000000000000000081565b34801561067f57600080fd5b5061028f61068e366004612425565b611456565b34801561069f57600080fd5b506106b36106ae366004612692565b611559565b60405161029b9190612736565b3480156106cc57600080fd5b506103436106db36600461233e565b6115cc565b3480156106ec57600080fd5b506102d860085481565b34801561070257600080fd5b5061034361071136600461233e565b611735565b34801561072257600080fd5b5061034361073136600461233e565b611817565b34801561074257600080fd5b506102d8620f424081565b34801561075957600080fd5b506102d861076836600461233e565b61187f565b34801561077957600080fd5b506102d87f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b3480156107ad57600080fd5b506103436107bc366004612425565b611896565b3480156107cd57600080fd5b506102d86107dc36600461281c565b60036020526000908152604090205481565b3480156107fa57600080fd5b506102d860045481565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f00000000000000000000000000000000000000000000000000000000148061085a575061085a826118bb565b92915050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561088a81611952565b6001600160a01b038316600090815260036020526040812054908190036108b15750505050565b6001600160a01b0384166000818152600360205260408120556108d590848361195f565b604080516001600160a01b038087168252851660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b505050565b60008281526020819052604090206001015461094281611952565b61094c8383611a82565b50505050565b6001600160a01b0381163314610994576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109228282611ab7565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc46109c881611952565b8251602084012060006109da85611559565b9050600260008381526005602052604090205460ff166004811115610a0157610a01612357565b14610a38576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660209081526040918290208251808401909352546bffffffffffffffffffffffff811683526c0100000000000000000000000090046001600160a01b03169082018190523314610abb576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611610b08576040517f1992d0bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600560205260409020805460ff1916600317905561010082015115610b645761010082015160808301516001600160a01b031660009081526003602052604081208054909190610b5e908490612868565b90915550505b608082015160c0830151610b826001600160a01b038316888361195f565b604080516001600160a01b03848116825260208201849052891691339188917f582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac67891015b60405180910390a45050505050505050565b46816000015163ffffffff1603610c1a576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a08101511580610c2d575060c0810151155b15610c64576040517fe38820c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608101516001600160a01b03161580610c89575060808101516001600160a01b0316155b15610cc0576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ccc61070842612868565b8161010001511015610d0a576040517f04b7fcc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d1f3083606001518460a00151611ae4565b90506000806002541115610d4c57620f424060025483610d3f919061287b565b610d499190612892565b90505b610d5681836128cd565b915060006040518061018001604052804663ffffffff168152602001856000015163ffffffff16815260200185602001516001600160a01b0316815260200185604001516001600160a01b0316815260200185606001516001600160a01b0316815260200185608001516001600160a01b031681526020018481526020018560c0015181526020018381526020018560e0015115158152602001856101000151815260200160086000815480929190610e0e906128e0565b909155509052604051610e249190602001612736565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152828252805160208083019190912060008181526005835293909320805460ff191660011790558701518751606089015160808a015160c08b015160e08c015195985095966001600160a01b039094169587957f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a95610ed6958b959094909390928e9261293c565b60405180910390a35050505050565b805160208201206000610ef783611559565b3360009081527fd2043bf65931af3dbecf60d0db8f40e4160406d7beb00522f4200cf4944a1eb8602052604090205490915060ff1615610f74578061014001514211610f6f576040517fe15ff9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fc0565b62093a80816101400151610f889190612868565b4211610fc0576040517fe15ff9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008381526005602052604090205460ff166004811115610fe557610fe5612357565b1461101c576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260056020526040808220805460ff19166004179055820151608083015161010084015160c0850151929391926110579190612868565b905061106d6001600160a01b038316848361195f565b604080516001600160a01b0384811682526020820184905285169187917fb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958910160405180910390a3505050505050565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc46110e781611952565b82516020840120600160008281526005602052604090205460ff16600481111561111357611113612357565b1461114a576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526005602090815260408083208054600260ff19909116179055805180820182526bffffffffffffffffffffffff4281168252338285018181528787526006865295849020925195516001600160a01b03166c0100000000000000000000000002959091169490941790555185815283917f4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4910160405180910390a350505050565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc461121a81611952565b81516020830120600061122c84611559565b90504663ffffffff16816020015163ffffffff1614611277576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8061014001514211156112b6576040517f559895a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526007602052604090205460ff16156112ff576040517fbef7bb7d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600760205260409020805460ff19166001179055606081015160a082015160e083015160045461012085015161134857506000611342848484611ae4565b506113b9565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b0384160161138c5761134284846113878486612868565b611ae4565b611397848484611ae4565b506113b78473eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee83611ae4565b505b845160808087015160a08089015160c0808b015160e08c01516040805163ffffffff90991689526001600160a01b0396871660208a0152938616938801939093526060870152938501528301849052861691339189917ff8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c9101610bc5565b600082815260016020526040812061144f9083611cb3565b9392505050565b6000600260008481526005602052604090205460ff16600481111561147d5761147d612357565b146114b4576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600660209081526040918290208251808401909352546bffffffffffffffffffffffff811683526001600160a01b036c01000000000000000000000000909104811691830182905284161461153a576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611949350505050565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201528251909161085a91840181019084016129ed565b7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d6115f681611952565b600260008381526005602052604090205460ff16600481111561161b5761161b612357565b14611652576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660209081526040918290208251808401909352546bffffffffffffffffffffffff8082168085526c010000000000000000000000009092046001600160a01b031693909201929092526107089142031611156116e1576040517f3e908aac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040808320805460ff19166001179055600690915280822082905551339184917f0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad49190a35050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561175f81611952565b6127108211156117d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064015b60405180910390fd5b600280549083905560408051828152602081018590527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a1505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561184181611952565b600480549083905560408051828152602081018590527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa910161180a565b600081815260016020526040812061085a90611cbf565b6000828152602081905260409020600101546118b181611952565b61094c8383611ab7565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061085a57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461085a565b61195c8133611cc9565b50565b306001600160a01b0383160361197457505050565b8060000361198157505050565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03841601611a6e576000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146119fe576040519150601f19603f3d011682016040523d82523d6000602084013e611a03565b606091505b505090508061094c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c65640000000000000000000000000060448201526064016117c7565b6109226001600160a01b0384168383611d39565b600080611a8f8484611dad565b9050801561144f576000848152600160205260409020611aaf9084611e57565b509392505050565b600080611ac48484611e6c565b9050801561144f576000848152600160205260409020611aaf9084611eef565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611c4d57611b1c836001600160a01b0316611f04565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528416906370a0823190602401602060405180830381865afa158015611b7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9f9190612ab9565b9050611bb66001600160a01b038416338685611faa565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528291908516906370a0823190602401602060405180830381865afa158015611c18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c3c9190612ab9565b611c4691906128cd565b905061144f565b348214611c86576040517f81de0bf300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0384163014611caa57611caa6001600160a01b038416858461195f565b50349392505050565b600061144f8383611fe3565b600061085a825490565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16611d35576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602481018390526044016117c7565b5050565b6040516001600160a01b0383811660248301526044820183905261092291859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061200d565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16611e4f576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055611e073390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161085a565b50600061085a565b600061144f836001600160a01b038416612089565b6000828152602081815260408083206001600160a01b038516845290915281205460ff1615611e4f576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161085a565b600061144f836001600160a01b0384166120d0565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03821601611f66576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03163b60000361195c576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b03848116602483015283811660448301526064820183905261094c9186918216906323b872dd90608401611d66565b6000826000018281548110611ffa57611ffa612ad2565b9060005260206000200154905092915050565b60006120226001600160a01b038416836121c3565b905080516000141580156120475750808060200190518101906120459190612b01565b155b15610922576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024016117c7565b6000818152600183016020526040812054611e4f5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561085a565b600081815260018301602052604081205480156121b95760006120f46001836128cd565b8554909150600090612108906001906128cd565b905080821461216d57600086600001828154811061212857612128612ad2565b906000526020600020015490508087600001848154811061214b5761214b612ad2565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061217e5761217e612b1e565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061085a565b600091505061085a565b606061144f8383600084600080856001600160a01b031684866040516121e99190612b4d565b60006040518083038185875af1925050503d8060008114612226576040519150601f19603f3d011682016040523d82523d6000602084013e61222b565b606091505b509150915061223b868383612245565b9695505050505050565b60608261225a57612255826122ba565b61144f565b815115801561227157506001600160a01b0384163b155b156122b3576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016117c7565b508061144f565b8051156122ca5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561230e57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461144f57600080fd5b60006020828403121561235057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600583106123c1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6001600160a01b038116811461195c57600080fd5b80356123e7816123c7565b919050565b600080604083850312156123ff57600080fd5b823561240a816123c7565b9150602083013561241a816123c7565b809150509250929050565b6000806040838503121561243857600080fd5b82359150602083013561241a816123c7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171561249d5761249d61244a565b60405290565b604051610180810167ffffffffffffffff8111828210171561249d5761249d61244a565b600082601f8301126124d857600080fd5b813567ffffffffffffffff808211156124f3576124f361244a565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156125395761253961244a565b8160405283815286602085880101111561255257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806040838503121561258557600080fd5b823567ffffffffffffffff81111561259c57600080fd5b6125a8858286016124c7565b925050602083013561241a816123c7565b63ffffffff8116811461195c57600080fd5b80356123e7816125b9565b801515811461195c57600080fd5b80356123e7816125d6565b6000610120828403121561260257600080fd5b61260a612479565b612613836125cb565b8152612621602084016123dc565b6020820152612632604084016123dc565b6040820152612643606084016123dc565b6060820152612654608084016123dc565b608082015260a083013560a082015260c083013560c082015261267960e084016125e4565b60e0820152610100928301359281019290925250919050565b6000602082840312156126a457600080fd5b813567ffffffffffffffff8111156126bb57600080fd5b6126c7848285016124c7565b949350505050565b600080604083850312156126e257600080fd5b823567ffffffffffffffff8111156126f957600080fd5b612705858286016124c7565b95602094909401359450505050565b6000806040838503121561272757600080fd5b50508035926020909101359150565b815163ffffffff1681526101808101602083015161275c602084018263ffffffff169052565b50604083015161277760408401826001600160a01b03169052565b50606083015161279260608401826001600160a01b03169052565b5060808301516127ad60808401826001600160a01b03169052565b5060a08301516127c860a08401826001600160a01b03169052565b5060c083015160c083015260e083015160e0830152610100808401518184015250610120808401516127fd8285018215159052565b5050610140838101519083015261016092830151929091019190915290565b60006020828403121561282e57600080fd5b813561144f816123c7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561085a5761085a612839565b808202811582820484141761085a5761085a612839565b6000826128c8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561085a5761085a612839565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361291157612911612839565b5060010190565b60005b8381101561293357818101518382015260200161291b565b50506000910152565b60e08152600088518060e084015261010061295d8282860160208e01612918565b63ffffffff9990991660208401526001600160a01b039788166040840152959096166060820152608081019390935260a0830191909152151560c0820152601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190910192915050565b80516123e7816125b9565b80516123e7816123c7565b80516123e7816125d6565b60006101808284031215612a0057600080fd5b612a086124a3565b612a11836129cc565b8152612a1f602084016129cc565b6020820152612a30604084016129d7565b6040820152612a41606084016129d7565b6060820152612a52608084016129d7565b6080820152612a6360a084016129d7565b60a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120612a968185016129e2565b908201526101408381015190820152610160928301519281019290925250919050565b600060208284031215612acb57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215612b1357600080fd5b815161144f816125d6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612b5f818460208701612918565b919091019291505056fea26469706673582212207d038d8dfad42c58e5149b646b9e05914f990dd941b51e06388a96d1ed46308264736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"58205:11304:0:-:0;;;59380:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;59414:6;57196:38;46368:4;59414:6;57196:10;:38::i;:::-;-1:-1:-1;;59446:12:0::1;59432:26;::::0;-1:-1:-1;58205:11304:0;;55681:257;55767:4;;55798:31;55815:4;55821:7;55798:16;:31::i;:::-;55783:46;;55843:7;55839:69;;;55866:18;;;;:12;:18;;;;;:31;;55889:7;55866:22;:31::i;:::-;;55839:69;55924:7;-1:-1:-1;55681:257:0;;;;;:::o;50315:316::-;50392:4;47090:12;;;;;;;;;;;-1:-1:-1;;;;;47090:29:0;;;;;;;;;;;;50408:217;;50451:6;:12;;;;;;;;;;;-1:-1:-1;;;;;50451:29:0;;;;;;;;;:36;;-1:-1:-1;;50451:36:0;50483:4;50451:36;;;50533:12;22406:10;;22327:96;50533:12;-1:-1:-1;;;;;50506:40:0;50524:7;-1:-1:-1;;;;;50506:40:0;50518:4;50506:40;;;;;;;;;;-1:-1:-1;50567:4:0;50560:11;;50408:217;-1:-1:-1;50609:5:0;50602:12;;31852:150;31922:4;31945:50;31950:3;-1:-1:-1;;;;;31970:23:0;;25840:4;27896:21;;;:14;;;:21;;;;;;25856:321;;-1:-1:-1;25898:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;26080:18;;26056:21;;;:14;;;:21;;;;;;:42;;;;26112:11;;14:290:1;84:6;137:2;125:9;116:7;112:23;108:32;105:52;;;153:1;150;143:12;105:52;179:16;;-1:-1:-1;;;;;224:31:1;;214:42;;204:70;;270:1;267;260:12;14:290;58205:11304:0;;;;;;;;;;;;","srcMapRuntime":"58205:11304:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54341:212;;;;;;;;;;-1:-1:-1;54341:212:0;;;;;:::i;:::-;;:::i;:::-;;;612:14:1;;605:22;587:41;;575:2;560:18;54341:212:0;;;;;;;;56571:60;;;;;;;;;;;;56608:23;56571:60;;;;;785:25:1;;;773:2;758:18;56571:60:0;639:177:1;58932:54:0;;;;;;;;;;-1:-1:-1;58932:54:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;57543:359::-;;;;;;;;;;-1:-1:-1;57543:359:0;;;;;:::i;:::-;;:::i;:::-;;56753:45;;;;;;;;;;;;56792:6;56753:45;;58530;;;;;;;;;;;;58569:6;58530:45;;47946:120;;;;;;;;;;-1:-1:-1;47946:120:0;;;;;:::i;:::-;48011:7;48037:12;;;;;;;;;;:22;;;;47946:120;48362:136;;;;;;;;;;-1:-1:-1;48362:136:0;;;;;:::i;:::-;;:::i;49464:245::-;;;;;;;;;;-1:-1:-1;49464:245:0;;;;;:::i;:::-;;:::i;66607:1146::-;;;;;;;;;;-1:-1:-1;66607:1146:0;;;;;:::i;:::-;;:::i;61065:2114::-;;;;;;:::i;:::-;;:::i;56915:30::-;;;;;;;;;;;;;;;;56499:66;;;;;;;;;;;;56539:26;56499:66;;68354:1153;;;;;;;;;;-1:-1:-1;68354:1153:0;;;;;:::i;:::-;;:::i;58662:56::-;;;;;;;;;;;;58708:10;58662:56;;59177:44;;;;;;;;;;-1:-1:-1;59177:44:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;64973:567;;;;;;;;;;-1:-1:-1;64973:567:0;;;;;:::i;:::-;;:::i;63217:1718::-;;;;;;:::i;:::-;;:::i;55138:142::-;;;;;;;;;;-1:-1:-1;55138:142:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;7391:55:1;;;7373:74;;7361:2;7346:18;55138:142:0;7227:226:1;59051:51:0;;;;;;;;;;-1:-1:-1;59051:51:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;59051:51:0;;;;;;;7660:26:1;7648:39;;;7630:58;;-1:-1:-1;;;;;7724:55:1;;;7719:2;7704:18;;7697:83;7603:18;59051:51:0;7458:328:1;46990:136:0;;;;;;;;;;-1:-1:-1;46990:136:0;;;;;:::i;:::-;47067:4;47090:12;;;;;;;;;;;-1:-1:-1;;;;;47090:29:0;;;;;;;;;;;;;;;46990:136;56429:64;;;;;;;;;;;;56468:25;56429:64;;46323:49;;;;;;;;;;-1:-1:-1;46323:49:0;46368:4;46323:49;;59337:36;;;;;;;;;;;;;;;66196:373;;;;;;;;;;-1:-1:-1;66196:373:0;;;;;:::i;:::-;;:::i;60864:163::-;;;;;;;;;;-1:-1:-1;60864:163:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;67791:525::-;;;;;;;;;;-1:-1:-1;67791:525:0;;;;;:::i;:::-;;:::i;59260:20::-;;;;;;;;;;;;;;;;57247:290;;;;;;;;;;-1:-1:-1;57247:290:0;;;;;:::i;:::-;;:::i;57908:264::-;;;;;;;;;;-1:-1:-1;57908:264:0;;;;;:::i;:::-;;:::i;56710:37::-;;;;;;;;;;;;56744:3;56710:37;;55448:131;;;;;;;;;;-1:-1:-1;55448:131:0;;;;;:::i;:::-;;:::i;56637:66::-;;;;;;;;;;;;56677:26;56637:66;;48778:138;;;;;;;;;;-1:-1:-1;48778:138:0;;;;;:::i;:::-;;:::i;57001:47::-;;;;;;;;;;-1:-1:-1;57001:47:0;;;;;:::i;:::-;;;;;;;;;;;;;;57122:29;;;;;;;;;;;;;;;;54341:212;54426:4;54449:57;;;54464:42;54449:57;;:97;;;54510:36;54534:11;54510:23;:36::i;:::-;54442:104;54341:212;-1:-1:-1;;54341:212:0:o;57543:359::-;56677:26;46600:16;46611:4;46600:10;:16::i;:::-;-1:-1:-1;;;;;57667:19:0;::::1;57647:17;57667:19:::0;;;:12:::1;:19;::::0;;;;;;57700:14;;;57696:27:::1;;57716:7;57543:359:::0;;;:::o;57696:27::-:1;-1:-1:-1::0;;;;;57764:19:0;::::1;57786:1;57764:19:::0;;;:12:::1;:19;::::0;;;;:23;57797:45:::1;::::0;57821:9;57832;57797:23:::1;:45::i;:::-;57857:38;::::0;;-1:-1:-1;;;;;9986:15:1;;;9968:34;;10038:15;;10033:2;10018:18;;10011:43;10070:18;;;10063:34;;;57857:38:0::1;::::0;9895:2:1;9880:18;57857:38:0::1;;;;;;;57637:265;46626:1;57543:359:::0;;;:::o;48362:136::-;48011:7;48037:12;;;;;;;;;;:22;;;46600:16;46611:4;46600:10;:16::i;:::-;48466:25:::1;48477:4;48483:7;48466:10;:25::i;:::-;;48362:136:::0;;;:::o;49464:245::-;-1:-1:-1;;;;;49557:34:0;;22406:10;49557:34;49553:102;;49614:30;;;;;;;;;;;;;;49553:102;49665:37;49677:4;49683:18;49665:11;:37::i;66607:1146::-;56468:25;46600:16;46611:4;46600:10;:16::i;:::-;66722:18;;::::1;::::0;::::1;::::0;66698:21:::1;66789:29;66732:7:::0;66789:20:::1;:29::i;:::-;66750:68:::0;-1:-1:-1;66936:27:0::1;66903:29;::::0;;;:14:::1;:29;::::0;;;;;::::1;;:60;::::0;::::1;;;;;;:::i;:::-;;66899:90;;66972:17;;;;;;;;;;;;;;66899:90;67000:24;67027:27:::0;;;:12:::1;:27;::::0;;;;;;;;67000:54;;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;;;;::::1;-1:-1:-1::0;;;;;67000:54:0::1;::::0;;::::1;::::0;;;67085:10:::1;67068:27;67064:57;;67104:17;;;;;;;;;;;;;;67064:57;66126:15:::0;;58424:10:::1;::::0;66107:15;66100:41;66092:49;;67135:35:::1;67131:72;;67179:24;;;;;;;;;;;;;;67131:72;67214:29;::::0;;;:14:::1;:29;::::0;;;;:60;;-1:-1:-1;;67214:60:0::1;67246:28;67214:60;::::0;;67349:27:::1;::::0;::::1;::::0;:31;67345:105:::1;;67423:27;::::0;::::1;::::0;67395:23:::1;::::0;::::1;::::0;-1:-1:-1;;;;;67382:37:0::1;;::::0;;;:12:::1;:37;::::0;;;;:68;;:37;;;:68:::1;::::0;67423:27;;67382:68:::1;:::i;:::-;::::0;;;-1:-1:-1;;67345:105:0::1;67545:23;::::0;::::1;::::0;67595:24:::1;::::0;::::1;::::0;67629:35:::1;-1:-1:-1::0;;;;;67629:23:0;::::1;67653:2:::0;67595:24;67629:23:::1;:35::i;:::-;67680:66;::::0;;-1:-1:-1;;;;;10619:55:1;;;10601:74;;10706:2;10691:18;;10684:34;;;67680:66:0;::::1;::::0;67716:10:::1;::::0;67701:13;;67680:66:::1;::::0;10574:18:1;67680:66:0::1;;;;;;;;66688:1065;;;;;66607:1146:::0;;;:::o;61065:2114::-;61192:13;61171:6;:17;;;:34;;;61167:63;;61214:16;;;;;;;;;;;;;;61167:63;61244:19;;;;:24;;:50;;-1:-1:-1;61272:17:0;;;;:22;61244:50;61240:80;;;61303:17;;;;;;;;;;;;;;61240:80;61334:18;;;;-1:-1:-1;;;;;61334:32:0;;;:66;;-1:-1:-1;61370:16:0;;;;-1:-1:-1;;;;;61370:30:0;;61334:66;61330:92;;;61409:13;;;;;;;;;;;;;;61330:92;61454:37;58708:10;61454:15;:37;:::i;:::-;61436:6;:15;;;:55;61432:86;;;61500:18;;;;;;;;;;;;;;61432:86;61653:20;61676:66;61695:4;61702:6;:18;;;61722:6;:19;;;61676:10;:66::i;:::-;61653:89;;61810:23;61865:1;61847:15;;:19;61843:85;;;56744:3;61902:15;;61887:12;:30;;;;:::i;:::-;61886:42;;;;:::i;:::-;61868:60;;61843:85;61938:31;61954:15;61938:31;;:::i;:::-;;;62082:20;62129:618;;;;;;;;62187:13;62129:618;;;;;;62232:6;:17;;;62129:618;;;;;;62281:6;:13;;;-1:-1:-1;;;;;62129:618:0;;;;;62327:6;:9;;;-1:-1:-1;;;;;62129:618:0;;;;;62367:6;:18;;;-1:-1:-1;;;;;62129:618:0;;;;;62414:6;:16;;;-1:-1:-1;;;;;62129:618:0;;;;;62462:12;62129:618;;;;62504:6;:17;;;62129:618;;;;62556:15;62129:618;;;;62603:6;:19;;;62129:618;;;;;;62650:6;:15;;;62129:618;;;;62690:5;;:7;;;;;;;;;:::i;:::-;;;;-1:-1:-1;62129:618:0;;62105:652;;;;;;;;:::i;:::-;;;;;;;;;;;;;;62791:18;;62105:652;62791:18;;;;;;;62767:21;62819:29;;;:14;:29;;;;;;:54;;-1:-1:-1;;62819:54:0;62851:22;62819:54;;;62945:13;;;62993:17;;63024:18;;;;63056:16;;;;63112:17;;;;63143:19;;;;62105:652;;-1:-1:-1;62791:18:0;;-1:-1:-1;;;;;62889:283:0;;;;62791:18;;62889:283;;;;62105:652;;62993:17;;63024:18;;63056:16;;63086:12;;62889:283;:::i;:::-;;;;;;;;61126:2053;;;;61065:2114;:::o;68354:1153::-;68435:18;;;;;;68411:21;68502:29;68445:7;68502:20;:29::i;:::-;68569:10;47067:4;47090:29;;;:12;;:29;:12;:29;;;68463:68;;-1:-1:-1;47090:29:0;;68542:382;;;68677:11;:20;;;68658:15;:39;68654:73;;68706:21;;;;;;;;;;;;;;68654:73;68542:382;;;58569:6;68848:11;:20;;;:35;;;;:::i;:::-;68829:15;:54;68825:88;;68892:21;;;;;;;;;;;;;;68825:88;69033:22;69000:29;;;;:14;:29;;;;;;;;:55;;;;;;;;:::i;:::-;;68996:85;;69064:17;;;;;;;;;;;;;;68996:85;69091:29;;;;:14;:29;;;;;;:53;;-1:-1:-1;;69091:53:0;69123:21;69091:53;;;69230:24;;;69280:23;;;;69357:27;;;;69330:24;;;;69230;;69280:23;;69330:54;;69357:27;69330:54;:::i;:::-;69313:71;-1:-1:-1;69394:35:0;-1:-1:-1;;;;;69394:23:0;;69418:2;69313:71;69394:23;:35::i;:::-;69445:55;;;-1:-1:-1;;;;;10619:55:1;;;10601:74;;10706:2;10691:18;;10684:34;;;69445:55:0;;;69467:13;;69445:55;;10574:18:1;69445:55:0;;;;;;;68401:1106;;;;;68354:1153;:::o;64973:567::-;56468:25;46600:16;46611:4;46600:10;:16::i;:::-;65096:18;;::::1;::::0;::::1;::::0;65217:22:::1;65184:29;::::0;;;:14:::1;:29;::::0;;;;;::::1;;:55;::::0;::::1;;;;;;:::i;:::-;;65180:85;;65248:17;;;;;;;;;;;;;;65180:85;65275:29;::::0;;;:14:::1;:29;::::0;;;;;;;:59;;65307:27:::1;-1:-1:-1::0;;65275:59:0;;::::1;;::::0;;65374:70;;;;::::1;::::0;;::::1;65405:15;65374:70:::0;::::1;::::0;;65432:10:::1;65374:70:::0;;::::1;::::0;;;65344:27;;;:12:::1;:27:::0;;;;;;:100;;;;-1:-1:-1;;;;;65344:100:0::1;::::0;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;65475:58;785:25:1;;;65275:29:0;;65475:58:::1;::::0;758:18:1;65475:58:0::1;;;;;;;65062:478;64973:567:::0;;;:::o;63217:1718::-;56468:25;46600:16;46611:4;46600:10;:16::i;:::-;63328:18;;::::1;::::0;::::1;::::0;63304:21:::1;63395:29;63338:7:::0;63395:20:::1;:29::i;:::-;63356:68;;63472:13;63438:48;;:11;:23;;;:48;;;63434:77;;63495:16;;;;;;;;;;;;;;63434:77;63607:11;:20;;;63589:15;:38;63585:69;;;63636:18;;;;;;;;;;;;;;63585:69;63715:27;::::0;;;:12:::1;:27;::::0;;;;;::::1;;63711:60;;;63751:20;;;;;;;;;;;;;;63711:60;63781:27;::::0;;;:12:::1;:27;::::0;;;;:34;;-1:-1:-1;;63781:34:0::1;63811:4;63781:34;::::0;;63928:25:::1;::::0;::::1;::::0;63979:21:::1;::::0;::::1;::::0;64027:22:::1;::::0;::::1;::::0;64077:14:::1;::::0;64106:24:::1;::::0;::::1;::::0;64101:517:::1;;-1:-1:-1::0;64184:1:0::1;64199:29;64210:2:::0;64214:5;64221:6;64199:10:::1;:29::i;:::-;;64101:517;;;64249:38:::0;-1:-1:-1;;;;;64249:38:0;::::1;::::0;64245:373:::1;;64369:38;64380:2:::0;64384:5;64391:15:::1;64400:6:::0;64391;:15:::1;:::i;:::-;64369:10;:38::i;64245:373::-;64511:29;64522:2;64526:5;64533:6;64511:10;:29::i;:::-;;64554:53;64565:2;51330:42;64600:6;64554:10;:53::i;:::-;;64245:373;64727:25:::0;;64766:23:::1;::::0;;::::1;::::0;64803:21:::1;::::0;;::::1;::::0;64838:24:::1;::::0;;::::1;::::0;64876:22:::1;::::0;::::1;::::0;64633:295:::1;::::0;;13103:10:1;13091:23;;;13073:42;;-1:-1:-1;;;;;13212:15:1;;;13207:2;13192:18;;13185:43;13264:15;;;13244:18;;;13237:43;;;;13311:2;13296:18;;13289:34;13339:19;;;13332:35;13383:19;;13376:35;;;64633:295:0;::::1;::::0;64687:10:::1;::::0;64660:13;;64633:295:::1;::::0;13045:19:1;64633:295:0::1;12788:629:1::0;55138:142:0;55219:7;55245:18;;;:12;:18;;;;;:28;;55267:5;55245:21;:28::i;:::-;55238:35;55138:142;-1:-1:-1;;;55138:142:0:o;66196:373::-;66277:4;66330:27;66297:29;;;;:14;:29;;;;;;;;:60;;;;;;;;:::i;:::-;;66293:90;;66366:17;;;;;;;;;;;;;;66293:90;66393:24;66420:27;;;:12;:27;;;;;;;;;66393:54;;;;;;;;;;;;;;-1:-1:-1;;;;;66393:54:0;;;;;;;;;;;;66461:24;;;66457:54;;66494:17;;;;;;;;;;;;;;66457:54;66126:15;;58424:10;;66107:15;66100:41;66092:49;;66528:34;;66196:373;-1:-1:-1;;;;66196:373:0:o;60864:163::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60980:40:0;;-1:-1:-1;;60980:40:0;;;;;;;;;;:::i;67791:525::-;56608:23;46600:16;46611:4;46600:10;:16::i;:::-;67908:27:::1;67875:29;::::0;;;:14:::1;:29;::::0;;;;;::::1;;:60;::::0;::::1;;;;;;:::i;:::-;;67871:90;;67944:17;;;;;;;;;;;;;;67871:90;67986:27;::::0;;;:12:::1;:27;::::0;;;;;;;;67975:39;;;;::::1;::::0;;;;::::1;::::0;;::::1;::::0;;;;;;::::1;-1:-1:-1::0;;;;;67975:39:0::1;::::0;;;::::1;::::0;;;;58424:10:::1;::::0;66107:15;66100:41;66092:49;67975:56:::1;67971:90;;;68040:21;;;;;;;;;;;;;;67971:90;68149:29;::::0;;;:14:::1;:29;::::0;;;;;;;:54;;-1:-1:-1;;68149:54:0::1;68181:22;68149:54;::::0;;68220:12:::1;:27:::0;;;;;;68213:34;;;68263:46;68298:10:::1;::::0;68149:29;;68263:46:::1;::::0;68149:29;68263:46:::1;67791:525:::0;;:::o;57247:290::-;56677:26;46600:16;46611:4;46600:10;:16::i;:::-;56792:6:::1;57346:10;:26;;57338:55;;;::::0;::::1;::::0;;15233:2:1;57338:55:0::1;::::0;::::1;15215:21:1::0;15272:2;15252:18;;;15245:30;15311:18;15291;;;15284:46;15347:18;;57338:55:0::1;;;;;;;;;57424:15;::::0;;57449:28;;;;57492:38:::1;::::0;;15550:25:1;;;15606:2;15591:18;;15584:34;;;57492:38:0::1;::::0;15523:18:1;57492:38:0::1;;;;;;;;57328:209;57247:290:::0;;:::o;57908:264::-;56677:26;46600:16;46611:4;46600:10;:16::i;:::-;58033:14:::1;::::0;;58057:34;;;;58106:59:::1;::::0;;15550:25:1;;;15606:2;15591:18;;15584:34;;;58106:59:0::1;::::0;15523:18:1;58106:59:0::1;15376:248:1::0;55448:131:0;55519:7;55545:18;;;:12;:18;;;;;:27;;:25;:27::i;48778:138::-;48011:7;48037:12;;;;;;;;;;:22;;;46600:16;46611:4;46600:10;:16::i;:::-;48883:26:::1;48895:4;48901:7;48883:11;:26::i;46701:202::-:0;46786:4;46809:47;;;46824:32;46809:47;;:87;;-1:-1:-1;38614:25:0;38599:40;;;;46860:36;38500:146;47335:103;47401:30;47412:4;22406:10;47401;:30::i;:::-;47335:103;:::o;51613:653::-;51788:4;-1:-1:-1;;;;;51774:19:0;;;51770:32;;51613:653;;;:::o;51770:32::-;51874:5;51883:1;51874:10;51870:23;;51613:653;;;:::o;51870:23::-;51906:20;-1:-1:-1;;;;;51906:20:0;;;51902:358;;52086:12;52103:2;-1:-1:-1;;;;;52103:7:0;52118:5;52103:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52085:43;;;52150:7;52142:39;;;;;;;16041:2:1;52142:39:0;;;16023:21:1;16080:2;16060:18;;;16053:30;16119:21;16099:18;;;16092:49;16158:18;;52142:39:0;15839:343:1;51902:358:0;52212:37;-1:-1:-1;;;;;52212:26:0;;52239:2;52243:5;52212:26;:37::i;55681:257::-;55767:4;55783:12;55798:31;55815:4;55821:7;55798:16;:31::i;:::-;55783:46;;55843:7;55839:69;;;55866:18;;;;:12;:18;;;;;:31;;55889:7;55866:22;:31::i;:::-;;55924:7;55681:257;-1:-1:-1;;;55681:257:0:o;56041:262::-;56128:4;56144:12;56159:32;56177:4;56183:7;56159:17;:32::i;:::-;56144:47;;56205:7;56201:72;;;56228:18;;;;:12;:18;;;;;:34;;56254:7;56228:25;:34::i;59649:1177::-;59737:20;-1:-1:-1;;;;;59773:38:0;;51330:42;59773:38;59769:1051;;59827:24;:5;-1:-1:-1;;;;;59827:22:0;;:24::i;:::-;59932:34;;;;;-1:-1:-1;;;;;7391:55:1;;;59932:34:0;;;7373:74:1;59932:23:0;;;;;7346:18:1;;59932:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;59917:49;-1:-1:-1;60112:61:0;-1:-1:-1;;;;;60112:30:0;;60143:10;60155:9;60166:6;60112:30;:61::i;:::-;60309:34;;;;;-1:-1:-1;;;;;7391:55:1;;;60309:34:0;;;7373:74:1;60346:12:0;;60309:23;;;;;;7346:18:1;;60309:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:49;;;;:::i;:::-;60294:64;;59769:1051;;;60480:9;60470:6;:19;60466:51;;60498:19;;;;;;;;;;;;;;60466:51;-1:-1:-1;;;;;60598:26:0;;60619:4;60598:26;60594:74;;60626:42;-1:-1:-1;;;;;60626:23:0;;60650:9;60661:6;60626:23;:42::i;:::-;-1:-1:-1;60800:9:0;59649:1177;;;;;:::o;33110:156::-;33184:7;33234:22;33238:3;33250:5;33234:3;:22::i;32653:115::-;32716:7;32742:19;32750:3;28092:18;;28010:107;47568:197;47067:4;47090:12;;;;;;;;;;;-1:-1:-1;;;;;47090:29:0;;;;;;;;;;;;47651:108;;47701:47;;;;;-1:-1:-1;;;;;10619:55:1;;47701:47:0;;;10601:74:1;10691:18;;;10684:34;;;10574:18;;47701:47:0;10427:297:1;47651:108:0;47568:197;;:::o;39818:160::-;39927:43;;-1:-1:-1;;;;;10619:55:1;;;39927:43:0;;;10601:74:1;10691:18;;;10684:34;;;39900:71:0;;39920:5;;39942:14;;;;;10574:18:1;;39927:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39900:19;:71::i;50315:316::-;50392:4;47090:12;;;;;;;;;;;-1:-1:-1;;;;;47090:29:0;;;;;;;;;;;;50408:217;;50451:6;:12;;;;;;;;;;;-1:-1:-1;;;;;50451:29:0;;;;;;;;;:36;;-1:-1:-1;;50451:36:0;50483:4;50451:36;;;50533:12;22406:10;;22327:96;50533:12;-1:-1:-1;;;;;50506:40:0;50524:7;-1:-1:-1;;;;;50506:40:0;50518:4;50506:40;;;;;;;;;;-1:-1:-1;50567:4:0;50560:11;;50408:217;-1:-1:-1;50609:5:0;50602:12;;31852:150;31922:4;31945:50;31950:3;-1:-1:-1;;;;;31970:23:0;;31945:4;:50::i;50866:317::-;50944:4;47090:12;;;;;;;;;;;-1:-1:-1;;;;;47090:29:0;;;;;;;;;;;;50960:217;;;51034:5;51002:12;;;;;;;;;;;-1:-1:-1;;;;;51002:29:0;;;;;;;;;;:37;;-1:-1:-1;;51002:37:0;;;51058:40;22406:10;;51002:12;;51058:40;;51034:5;51058:40;-1:-1:-1;51119:4:0;51112:11;;32170:156;32243:4;32266:53;32274:3;-1:-1:-1;;;;;32294:23:0;;32266:7;:53::i;53430:344::-;53597:38;-1:-1:-1;;;;;53597:38:0;;;53593:69;;53644:18;;;;;;;;;;;;;;53593:69;53718:5;-1:-1:-1;;;;;53718:17:0;;53739:1;53718:22;53714:53;;53749:18;;;;;;;;;;;;;;40217:188;40344:53;;-1:-1:-1;;;;;9986:15:1;;;40344:53:0;;;9968:34:1;10038:15;;;10018:18;;;10011:43;10070:18;;;10063:34;;;40317:81:0;;40337:5;;40359:18;;;;;9880::1;;40344:53:0;9705:398:1;28459:118:0;28526:7;28552:3;:11;;28564:5;28552:18;;;;;;;;:::i;:::-;;;;;;;;;28545:25;;28459:118;;;;:::o;42574:629::-;42993:23;43019:33;-1:-1:-1;;;;;43019:27:0;;43047:4;43019:27;:33::i;:::-;42993:59;;43066:10;:17;43087:1;43066:22;;:57;;;;;43104:10;43093:30;;;;;;;;;;;;:::i;:::-;43092:31;43066:57;43062:135;;;43146:40;;;;;-1:-1:-1;;;;;7391:55:1;;43146:40:0;;;7373:74:1;7346:18;;43146:40:0;7227:226:1;25777:406:0;25840:4;27896:21;;;:14;;;:21;;;;;;25856:321;;-1:-1:-1;25898:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;26080:18;;26056:21;;;:14;;;:21;;;;;;:42;;;;26112:11;;26351:1368;26417:4;26546:21;;;:14;;;:21;;;;;;26582:13;;26578:1135;;26949:18;26970:12;26981:1;26970:8;:12;:::i;:::-;27016:18;;26949:33;;-1:-1:-1;26996:17:0;;27016:22;;27037:1;;27016:22;:::i;:::-;26996:42;;27071:9;27057:10;:23;27053:378;;27100:17;27120:3;:11;;27132:9;27120:22;;;;;;;;:::i;:::-;;;;;;;;;27100:42;;27267:9;27241:3;:11;;27253:10;27241:23;;;;;;;;:::i;:::-;;;;;;;;;;;;:35;;;;27380:25;;;:14;;;:25;;;;;:36;;;27053:378;27509:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;27612:3;:14;;:21;27627:5;27612:21;;;;;;;;;;;27605:28;;;27655:4;27648:11;;;;;;;26578:1135;27697:5;27690:12;;;;;18112:151;18187:12;18218:38;18240:6;18248:4;18254:1;18187:12;18828;18842:23;18869:6;-1:-1:-1;;;;;18869:11:0;18888:5;18895:4;18869:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18827:73;;;;18917:55;18944:6;18952:7;18961:10;18917:26;:55::i;:::-;18910:62;18587:392;-1:-1:-1;;;;;;18587:392:0:o;20032:582::-;20176:12;20205:7;20200:408;;20228:19;20236:10;20228:7;:19::i;:::-;20200:408;;;20452:17;;:22;:49;;;;-1:-1:-1;;;;;;20478:18:0;;;:23;20452:49;20448:119;;;20528:24;;;;;-1:-1:-1;;;;;7391:55:1;;20528:24:0;;;7373:74:1;7346:18;;20528:24:0;7227:226:1;20448:119:0;-1:-1:-1;20587:10:0;20580:17;;21150:516;21281:17;;:21;21277:383;;21509:10;21503:17;21565:15;21552:10;21548:2;21544:19;21537:44;21277:383;21632:17;;;;;;;;;;;;;;14:332:1;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;180:9;167:23;230:66;223:5;219:78;212:5;209:89;199:117;;312:1;309;302:12;821:180;880:6;933:2;921:9;912:7;908:23;904:32;901:52;;;949:1;946;939:12;901:52;-1:-1:-1;972:23:1;;821:180;-1:-1:-1;821:180:1:o;1006:184::-;1058:77;1055:1;1048:88;1155:4;1152:1;1145:15;1179:4;1176:1;1169:15;1195:402;1344:2;1329:18;;1377:1;1366:13;;1356:201;;1413:77;1410:1;1403:88;1514:4;1511:1;1504:15;1542:4;1539:1;1532:15;1356:201;1566:25;;;1195:402;:::o;1602:154::-;-1:-1:-1;;;;;1681:5:1;1677:54;1670:5;1667:65;1657:93;;1746:1;1743;1736:12;1761:134;1829:20;;1858:31;1829:20;1858:31;:::i;:::-;1761:134;;;:::o;1900:388::-;1968:6;1976;2029:2;2017:9;2008:7;2004:23;2000:32;1997:52;;;2045:1;2042;2035:12;1997:52;2084:9;2071:23;2103:31;2128:5;2103:31;:::i;:::-;2153:5;-1:-1:-1;2210:2:1;2195:18;;2182:32;2223:33;2182:32;2223:33;:::i;:::-;2275:7;2265:17;;;1900:388;;;;;:::o;2475:315::-;2543:6;2551;2604:2;2592:9;2583:7;2579:23;2575:32;2572:52;;;2620:1;2617;2610:12;2572:52;2656:9;2643:23;2633:33;;2716:2;2705:9;2701:18;2688:32;2729:31;2754:5;2729:31;:::i;2795:184::-;2847:77;2844:1;2837:88;2944:4;2941:1;2934:15;2968:4;2965:1;2958:15;2984:252;3056:2;3050:9;3098:3;3086:16;;3132:18;3117:34;;3153:22;;;3114:62;3111:88;;;3179:18;;:::i;:::-;3215:2;3208:22;2984:252;:::o;3241:247::-;3308:2;3302:9;3350:3;3338:16;;3384:18;3369:34;;3405:22;;;3366:62;3363:88;;;3431:18;;:::i;3493:777::-;3535:5;3588:3;3581:4;3573:6;3569:17;3565:27;3555:55;;3606:1;3603;3596:12;3555:55;3642:6;3629:20;3668:18;3705:2;3701;3698:10;3695:36;;;3711:18;;:::i;:::-;3845:2;3839:9;3907:4;3899:13;;3750:66;3895:22;;;3919:2;3891:31;3887:40;3875:53;;;3943:18;;;3963:22;;;3940:46;3937:72;;;3989:18;;:::i;:::-;4029:10;4025:2;4018:22;4064:2;4056:6;4049:18;4110:3;4103:4;4098:2;4090:6;4086:15;4082:26;4079:35;4076:55;;;4127:1;4124;4117:12;4076:55;4191:2;4184:4;4176:6;4172:17;4165:4;4157:6;4153:17;4140:54;4238:1;4231:4;4226:2;4218:6;4214:15;4210:26;4203:37;4258:6;4249:15;;;;;;3493:777;;;;:::o;4275:455::-;4352:6;4360;4413:2;4401:9;4392:7;4388:23;4384:32;4381:52;;;4429:1;4426;4419:12;4381:52;4469:9;4456:23;4502:18;4494:6;4491:30;4488:50;;;4534:1;4531;4524:12;4488:50;4557:49;4598:7;4589:6;4578:9;4574:22;4557:49;:::i;:::-;4547:59;;;4656:2;4645:9;4641:18;4628:32;4669:31;4694:5;4669:31;:::i;4735:121::-;4820:10;4813:5;4809:22;4802:5;4799:33;4789:61;;4846:1;4843;4836:12;4861:132;4928:20;;4957:30;4928:20;4957:30;:::i;4998:118::-;5084:5;5077:13;5070:21;5063:5;5060:32;5050:60;;5106:1;5103;5096:12;5121:128;5186:20;;5215:28;5186:20;5215:28;:::i;5254:865::-;5342:6;5395:3;5383:9;5374:7;5370:23;5366:33;5363:53;;;5412:1;5409;5402:12;5363:53;5438:22;;:::i;:::-;5483:28;5501:9;5483:28;:::i;:::-;5476:5;5469:43;5544:38;5578:2;5567:9;5563:18;5544:38;:::i;:::-;5539:2;5532:5;5528:14;5521:62;5615:38;5649:2;5638:9;5634:18;5615:38;:::i;:::-;5610:2;5603:5;5599:14;5592:62;5686:38;5720:2;5709:9;5705:18;5686:38;:::i;:::-;5681:2;5674:5;5670:14;5663:62;5758:39;5792:3;5781:9;5777:19;5758:39;:::i;:::-;5752:3;5745:5;5741:15;5734:64;5859:3;5848:9;5844:19;5831:33;5825:3;5818:5;5814:15;5807:58;5926:3;5915:9;5911:19;5898:33;5892:3;5885:5;5881:15;5874:58;5965:36;5996:3;5985:9;5981:19;5965:36;:::i;:::-;5959:3;5948:15;;5941:61;6021:3;6069:18;;;6056:32;6040:14;;;6033:56;;;;-1:-1:-1;5952:5:1;5254:865;-1:-1:-1;5254:865:1:o;6124:320::-;6192:6;6245:2;6233:9;6224:7;6220:23;6216:32;6213:52;;;6261:1;6258;6251:12;6213:52;6301:9;6288:23;6334:18;6326:6;6323:30;6320:50;;;6366:1;6363;6356:12;6320:50;6389:49;6430:7;6421:6;6410:9;6406:22;6389:49;:::i;:::-;6379:59;6124:320;-1:-1:-1;;;;6124:320:1:o;6449:388::-;6526:6;6534;6587:2;6575:9;6566:7;6562:23;6558:32;6555:52;;;6603:1;6600;6593:12;6555:52;6643:9;6630:23;6676:18;6668:6;6665:30;6662:50;;;6708:1;6705;6698:12;6662:50;6731:49;6772:7;6763:6;6752:9;6748:22;6731:49;:::i;:::-;6721:59;6827:2;6812:18;;;;6799:32;;-1:-1:-1;;;;6449:388:1:o;6842:248::-;6910:6;6918;6971:2;6959:9;6950:7;6946:23;6942:32;6939:52;;;6987:1;6984;6977:12;6939:52;-1:-1:-1;;7010:23:1;;;7080:2;7065:18;;;7052:32;;-1:-1:-1;6842:248:1:o;7890:1373::-;8121:13;;7867:10;7856:22;7844:35;;8090:3;8075:19;;8193:4;8185:6;8181:17;8175:24;8208:53;8255:4;8244:9;8240:20;8226:12;7867:10;7856:22;7844:35;;7791:94;8208:53;;8310:4;8302:6;8298:17;8292:24;8325:56;8375:4;8364:9;8360:20;8344:14;-1:-1:-1;;;;;7161:54:1;7149:67;;7095:127;8325:56;;8430:4;8422:6;8418:17;8412:24;8445:56;8495:4;8484:9;8480:20;8464:14;-1:-1:-1;;;;;7161:54:1;7149:67;;7095:127;8445:56;;8550:4;8542:6;8538:17;8532:24;8565:56;8615:4;8604:9;8600:20;8584:14;-1:-1:-1;;;;;7161:54:1;7149:67;;7095:127;8565:56;;8670:4;8662:6;8658:17;8652:24;8685:56;8735:4;8724:9;8720:20;8704:14;-1:-1:-1;;;;;7161:54:1;7149:67;;7095:127;8685:56;;8797:4;8789:6;8785:17;8779:24;8772:4;8761:9;8757:20;8750:54;8860:4;8852:6;8848:17;8842:24;8835:4;8824:9;8820:20;8813:54;8886:6;8946:2;8938:6;8934:15;8928:22;8923:2;8912:9;8908:18;8901:50;;8970:6;9025:2;9017:6;9013:15;9007:22;9038:51;9085:2;9074:9;9070:18;9054:14;421:13;414:21;402:34;;351:91;9038:51;-1:-1:-1;;9108:6:1;9156:15;;;9150:22;9130:18;;;9123:50;9192:6;9240:15;;;9234:22;9214:18;;;;9207:50;;;;7890:1373;:::o;9453:247::-;9512:6;9565:2;9553:9;9544:7;9540:23;9536:32;9533:52;;;9581:1;9578;9571:12;9533:52;9620:9;9607:23;9639:31;9664:5;9639:31;:::i;10108:184::-;10160:77;10157:1;10150:88;10257:4;10254:1;10247:15;10281:4;10278:1;10271:15;10297:125;10362:9;;;10383:10;;;10380:36;;;10396:18;;:::i;10729:168::-;10802:9;;;10833;;10850:15;;;10844:22;;10830:37;10820:71;;10871:18;;:::i;10902:274::-;10942:1;10968;10958:189;;11003:77;11000:1;10993:88;11104:4;11101:1;11094:15;11132:4;11129:1;11122:15;10958:189;-1:-1:-1;11161:9:1;;10902:274::o;11181:128::-;11248:9;;;11269:11;;;11266:37;;;11283:18;;:::i;11314:195::-;11353:3;11384:66;11377:5;11374:77;11371:103;;11454:18;;:::i;:::-;-1:-1:-1;11501:1:1;11490:13;;11314:195::o;11514:250::-;11599:1;11609:113;11623:6;11620:1;11617:13;11609:113;;;11699:11;;;11693:18;11680:11;;;11673:39;11645:2;11638:10;11609:113;;;-1:-1:-1;;11756:1:1;11738:16;;11731:27;11514:250::o;11769:1014::-;12076:3;12065:9;12058:22;12039:4;12109:6;12103:13;12153:6;12147:3;12136:9;12132:19;12125:35;12179:3;12191:81;12265:6;12260:2;12249:9;12245:18;12238:4;12230:6;12226:17;12191:81;:::i;:::-;12452:10;12440:23;;;;12433:4;12418:20;;12411:53;-1:-1:-1;;;;;12561:15:1;;;12556:2;12541:18;;12534:43;12613:15;;;;12608:2;12593:18;;12586:43;12660:3;12645:19;;12638:35;;;;12704:3;12689:19;;12682:35;;;;12761:14;12754:22;12748:3;12733:19;;12726:51;12324:2;12312:15;;;-1:-1:-1;12308:88:1;12293:104;12289:113;;;;;-1:-1:-1;;11769:1014:1:o;13422:136::-;13500:13;;13522:30;13500:13;13522:30;:::i;13563:138::-;13642:13;;13664:31;13642:13;13664:31;:::i;13706:132::-;13782:13;;13804:28;13782:13;13804:28;:::i;13843:1183::-;13946:6;13999:3;13987:9;13978:7;13974:23;13970:33;13967:53;;;14016:1;14013;14006:12;13967:53;14042:17;;:::i;:::-;14082:39;14111:9;14082:39;:::i;:::-;14075:5;14068:54;14154:48;14198:2;14187:9;14183:18;14154:48;:::i;:::-;14149:2;14142:5;14138:14;14131:72;14235:49;14280:2;14269:9;14265:18;14235:49;:::i;:::-;14230:2;14223:5;14219:14;14212:73;14317:49;14362:2;14351:9;14347:18;14317:49;:::i;:::-;14312:2;14305:5;14301:14;14294:73;14400:50;14445:3;14434:9;14430:19;14400:50;:::i;:::-;14394:3;14387:5;14383:15;14376:75;14484:50;14529:3;14518:9;14514:19;14484:50;:::i;:::-;14478:3;14471:5;14467:15;14460:75;14589:3;14578:9;14574:19;14568:26;14562:3;14555:5;14551:15;14544:51;14649:3;14638:9;14634:19;14628:26;14622:3;14615:5;14611:15;14604:51;14674:3;14730:2;14719:9;14715:18;14709:25;14704:2;14697:5;14693:14;14686:49;;14754:3;14789:46;14831:2;14820:9;14816:18;14789:46;:::i;:::-;14773:14;;;14766:70;14855:3;14896:18;;;14890:25;14874:14;;;14867:49;14935:3;14976:18;;;14970:25;14954:14;;;14947:49;;;;-1:-1:-1;14777:5:1;13843:1183;-1:-1:-1;13843:1183:1:o;16187:184::-;16257:6;16310:2;16298:9;16289:7;16285:23;16281:32;16278:52;;;16326:1;16323;16316:12;16278:52;-1:-1:-1;16349:16:1;;16187:184;-1:-1:-1;16187:184:1:o;16678:::-;16730:77;16727:1;16720:88;16827:4;16824:1;16817:15;16851:4;16848:1;16841:15;16867:245;16934:6;16987:2;16975:9;16966:7;16962:23;16958:32;16955:52;;;17003:1;17000;16993:12;16955:52;17035:9;17029:16;17054:28;17076:5;17054:28;:::i;17117:184::-;17169:77;17166:1;17159:88;17266:4;17263:1;17256:15;17290:4;17287:1;17280:15;17306:287;17435:3;17473:6;17467:13;17489:66;17548:6;17543:3;17536:4;17528:6;17524:17;17489:66;:::i;:::-;17571:16;;;;;17306:287;-1:-1:-1;;17306:287:1:o","abiDefinition":[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"AmountIncorrect","type":"error"},{"inputs":[],"name":"ChainIncorrect","type":"error"},{"inputs":[],"name":"DeadlineExceeded","type":"error"},{"inputs":[],"name":"DeadlineNotExceeded","type":"error"},{"inputs":[],"name":"DeadlineTooShort","type":"error"},{"inputs":[],"name":"DisputePeriodNotPassed","type":"error"},{"inputs":[],"name":"DisputePeriodPassed","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"MsgValueIncorrect","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"SenderIncorrect","type":"error"},{"inputs":[],"name":"StatusIncorrect","type":"error"},{"inputs":[],"name":"TokenNotContract","type":"error"},{"inputs":[],"name":"TransactionRelayed","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositRefunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"}],"name":"BridgeProofDisputed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":false,"internalType":"bytes32","name":"transactionHash","type":"bytes32"}],"name":"BridgeProofProvided","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint32","name":"originChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"chainGasAmount","type":"uint256"}],"name":"BridgeRelayed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes","name":"request","type":"bytes"},{"indexed":false,"internalType":"uint32","name":"destChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"sendChainGas","type":"bool"}],"name":"BridgeRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldChainGasAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"ChainGasAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFeeRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"FeeRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesSwept","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DISPUTE_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_RATE_MAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GOVERNOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GUARD_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_DEADLINE_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFUNDER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFUND_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAYER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstChainId","type":"uint32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IFastBridge.BridgeParams","name":"params","type":"tuple"}],"name":"bridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"bridgeProofs","outputs":[{"internalType":"uint96","name":"timestamp","type":"uint96"},{"internalType":"address","name":"relayer","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"bridgeRelays","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"bridgeStatuses","outputs":[{"internalType":"enum FastBridge.BridgeStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"address","name":"relayer","type":"address"}],"name":"canClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainGasAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"address","name":"to","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deployBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"dispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"getBridgeTransaction","outputs":[{"components":[{"internalType":"uint32","name":"originChainId","type":"uint32"},{"internalType":"uint32","name":"destChainId","type":"uint32"},{"internalType":"address","name":"originSender","type":"address"},{"internalType":"address","name":"destRecipient","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256","name":"originFeeAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct IFastBridge.BridgeTransaction","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"protocolFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"bytes32","name":"destTxHash","type":"bytes32"}],"name":"prove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"relay","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"setChainGasAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"setProtocolFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"sweepProtocolFees","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"DISPUTE_PERIOD()":{"notice":"Dispute period for relayed transactions"},"MIN_DEADLINE_PERIOD()":{"notice":"Minimum deadline period to relay a requested bridge transaction"},"REFUND_DELAY()":{"notice":"Delay for a transaction after which it could be permisionlessly refunded"},"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"notice":"Initiates bridge on origin chain to be relayed by off-chain relayer"},"bridgeProofs(bytes32)":{"notice":"Proof of relayed bridge tx on origin chain"},"bridgeRelays(bytes32)":{"notice":"Whether bridge has been relayed on destination chain"},"bridgeStatuses(bytes32)":{"notice":"Status of the bridge tx on origin chain"},"canClaim(bytes32,address)":{"notice":"Checks if the dispute period has passed so bridge deposit can be claimed"},"chainGasAmount()":{"notice":"Chain gas amount to forward as rebate if requested"},"claim(bytes,address)":{"notice":"Completes bridge transaction on origin chain by claiming originally deposited capital"},"dispute(bytes32)":{"notice":"Disputes an outstanding proof in case relayer provided dest chain tx is invalid"},"getBridgeTransaction(bytes)":{"notice":"Decodes bridge request into a bridge transaction"},"protocolFeeRate()":{"notice":"Protocol fee rate taken on origin amount deposited in origin chain"},"protocolFees(address)":{"notice":"Protocol fee amounts accumulated"},"prove(bytes,bytes32)":{"notice":"Provides proof on origin side that relayer provided funds on destination side of bridge transaction"},"refund(bytes)":{"notice":"Refunds an outstanding bridge transaction in case optimistic bridging failed"},"relay(bytes)":{"notice":"Relays destination side of bridge transaction by off-chain relayer"}},"version":1},"developerDoc":{"errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}],"AddressEmptyCode(address)":[{"details":"There's no code at `target` (it is not a contract)."}],"AddressInsufficientBalance(address)":[{"details":"The ETH balance of the account is not enough to perform the operation."}],"FailedInnerCall()":[{"details":"A call to an address target failed. The target may have reverted."}],"SafeERC20FailedOperation(address)":[{"details":"An operation with an ERC-20 token failed."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"params":{"params":"The parameters required to bridge"}},"canClaim(bytes32,address)":{"params":{"relayer":"The address of the relayer attempting to claim","transactionId":"The transaction id associated with the encoded bridge transaction to check"}},"claim(bytes,address)":{"params":{"request":"The encoded bridge transaction to claim on origin chain","to":"The recipient address of the funds"}},"dispute(bytes32)":{"params":{"transactionId":"The transaction id associated with the encoded bridge transaction to dispute"}},"getBridgeTransaction(bytes)":{"params":{"request":"The bridge request to decode"}},"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"getRoleMember(bytes32,uint256)":{"details":"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information."},"getRoleMemberCount(bytes32)":{"details":"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"prove(bytes,bytes32)":{"params":{"destTxHash":"The destination tx hash proving bridge transaction was relayed","request":"The encoded bridge transaction to prove on origin chain"}},"refund(bytes)":{"params":{"request":"The encoded bridge transaction to refund"}},"relay(bytes)":{"params":{"request":"The encoded bridge transaction to relay on destination chain"}},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"stateVariables":{"nonce":{"details":"to prevent replays"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineNotExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineTooShort\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputePeriodNotPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputePeriodPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MsgValueIncorrect\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SenderIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StatusIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenNotContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransactionRelayed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositRefunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"BridgeProofDisputed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"transactionHash\",\"type\":\"bytes32\"}],\"name\":\"BridgeProofProvided\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"BridgeRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"}],\"name\":\"BridgeRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DISPUTE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_DEADLINE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REFUNDER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REFUND_DELAY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"bridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeProofs\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"timestamp\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeRelays\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeStatuses\",\"outputs\":[{\"internalType\":\"enum FastBridge.BridgeStatus\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"canClaim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"dispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"getBridgeTransaction\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originSender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destRecipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originFeeAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeTransaction\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"destTxHash\",\"type\":\"bytes32\"}],\"name\":\"prove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"refund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}],\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"AddressInsufficientBalance(address)\":[{\"details\":\"The ETH balance of the account is not enough to perform the operation.\"}],\"FailedInnerCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"params\":{\"params\":\"The parameters required to bridge\"}},\"canClaim(bytes32,address)\":{\"params\":{\"relayer\":\"The address of the relayer attempting to claim\",\"transactionId\":\"The transaction id associated with the encoded bridge transaction to check\"}},\"claim(bytes,address)\":{\"params\":{\"request\":\"The encoded bridge transaction to claim on origin chain\",\"to\":\"The recipient address of the funds\"}},\"dispute(bytes32)\":{\"params\":{\"transactionId\":\"The transaction id associated with the encoded bridge transaction to dispute\"}},\"getBridgeTransaction(bytes)\":{\"params\":{\"request\":\"The bridge request to decode\"}},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"getRoleMember(bytes32,uint256)\":{\"details\":\"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.\"},\"getRoleMemberCount(bytes32)\":{\"details\":\"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"prove(bytes,bytes32)\":{\"params\":{\"destTxHash\":\"The destination tx hash proving bridge transaction was relayed\",\"request\":\"The encoded bridge transaction to prove on origin chain\"}},\"refund(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to refund\"}},\"relay(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to relay on destination chain\"}},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"stateVariables\":{\"nonce\":{\"details\":\"to prevent replays\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DISPUTE_PERIOD()\":{\"notice\":\"Dispute period for relayed transactions\"},\"MIN_DEADLINE_PERIOD()\":{\"notice\":\"Minimum deadline period to relay a requested bridge transaction\"},\"REFUND_DELAY()\":{\"notice\":\"Delay for a transaction after which it could be permisionlessly refunded\"},\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"notice\":\"Initiates bridge on origin chain to be relayed by off-chain relayer\"},\"bridgeProofs(bytes32)\":{\"notice\":\"Proof of relayed bridge tx on origin chain\"},\"bridgeRelays(bytes32)\":{\"notice\":\"Whether bridge has been relayed on destination chain\"},\"bridgeStatuses(bytes32)\":{\"notice\":\"Status of the bridge tx on origin chain\"},\"canClaim(bytes32,address)\":{\"notice\":\"Checks if the dispute period has passed so bridge deposit can be claimed\"},\"chainGasAmount()\":{\"notice\":\"Chain gas amount to forward as rebate if requested\"},\"claim(bytes,address)\":{\"notice\":\"Completes bridge transaction on origin chain by claiming originally deposited capital\"},\"dispute(bytes32)\":{\"notice\":\"Disputes an outstanding proof in case relayer provided dest chain tx is invalid\"},\"getBridgeTransaction(bytes)\":{\"notice\":\"Decodes bridge request into a bridge transaction\"},\"protocolFeeRate()\":{\"notice\":\"Protocol fee rate taken on origin amount deposited in origin chain\"},\"protocolFees(address)\":{\"notice\":\"Protocol fee amounts accumulated\"},\"prove(bytes,bytes32)\":{\"notice\":\"Provides proof on origin side that relayer provided funds on destination side of bridge transaction\"},\"refund(bytes)\":{\"notice\":\"Refunds an outstanding bridge transaction in case optimistic bridging failed\"},\"relay(bytes)\":{\"notice\":\"Relays destination side of bridge transaction by off-chain relayer\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"FastBridge\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x7da00701c906b2b78d838eb9c510ab5903b6dd7f8e5fb12d4c4710c350e3c919\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://faff50fb8d1f3cf10122c1b611d0987ca58f4099d90c17163816c90d3077bce7\",\"dweb:/ipfs/QmWKF2L9D18J9QXiMbm6ucj3x8ebjQtTrycnkNmB4q3JRo\"]}},\"version\":1}"},"hashes":{"DEFAULT_ADMIN_ROLE()":"a217fddf","DISPUTE_PERIOD()":"a5bbe22b","FEE_BPS()":"bf333f2c","FEE_RATE_MAX()":"0f5f6ed7","GOVERNOR_ROLE()":"ccc57490","GUARD_ROLE()":"03ed0ee5","MIN_DEADLINE_PERIOD()":"820688d5","REFUNDER_ROLE()":"5960ccf2","REFUND_DELAY()":"190da595","RELAYER_ROLE()":"926d7d7f","bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":"45851694","bridgeProofs(bytes32)":"91ad5039","bridgeRelays(bytes32)":"8379a24f","bridgeStatuses(bytes32)":"051287bc","canClaim(bytes32,address)":"aa9641ab","chainGasAmount()":"e00a83e0","claim(bytes,address)":"41fcb612","deployBlock()":"a3ec191a","dispute(bytes32)":"add98c70","getBridgeTransaction(bytes)":"ac11fb1a","getRoleAdmin(bytes32)":"248a9ca3","getRoleMember(bytes32,uint256)":"9010d07c","getRoleMemberCount(bytes32)":"ca15c873","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","nonce()":"affed0e0","protocolFeeRate()":"58f85880","protocolFees(address)":"dcf844a7","prove(bytes,bytes32)":"886d36ff","refund(bytes)":"5eb7d946","relay(bytes)":"8f0d6f17","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","setChainGasAmount(uint256)":"b250fe6b","setProtocolFeeRate(uint256)":"b13aa2d6","supportsInterface(bytes4)":"01ffc9a7","sweepProtocolFees(address,address)":"06f333f2"}},"solidity/FastBridge.sol:IAccessControl":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"External interface of AccessControl declared to support ERC-165 detection.","errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {AccessControl-_setRoleAdmin}."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"External interface of AccessControl declared to support ERC-165 detection.\",\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {AccessControl-_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"IAccessControl\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x7da00701c906b2b78d838eb9c510ab5903b6dd7f8e5fb12d4c4710c350e3c919\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://faff50fb8d1f3cf10122c1b611d0987ca58f4099d90c17163816c90d3077bce7\",\"dweb:/ipfs/QmWKF2L9D18J9QXiMbm6ucj3x8ebjQtTrycnkNmB4q3JRo\"]}},\"version\":1}"},"hashes":{"getRoleAdmin(bytes32)":"248a9ca3","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f"}},"solidity/FastBridge.sol:IAccessControlEnumerable":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"External interface of AccessControlEnumerable declared to support ERC-165 detection.","errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {AccessControl-_setRoleAdmin}."},"getRoleMember(bytes32,uint256)":{"details":"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information."},"getRoleMemberCount(bytes32)":{"details":"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"External interface of AccessControlEnumerable declared to support ERC-165 detection.\",\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {AccessControl-_setRoleAdmin}.\"},\"getRoleMember(bytes32,uint256)\":{\"details\":\"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.\"},\"getRoleMemberCount(bytes32)\":{\"details\":\"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"IAccessControlEnumerable\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x7da00701c906b2b78d838eb9c510ab5903b6dd7f8e5fb12d4c4710c350e3c919\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://faff50fb8d1f3cf10122c1b611d0987ca58f4099d90c17163816c90d3077bce7\",\"dweb:/ipfs/QmWKF2L9D18J9QXiMbm6ucj3x8ebjQtTrycnkNmB4q3JRo\"]}},\"version\":1}"},"hashes":{"getRoleAdmin(bytes32)":"248a9ca3","getRoleMember(bytes32,uint256)":"9010d07c","getRoleMemberCount(bytes32)":"ca15c873","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f"}},"solidity/FastBridge.sol:IAdmin":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldChainGasAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"ChainGasAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFeeRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"FeeRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesSwept","type":"event"},{"inputs":[{"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"setChainGasAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"setProtocolFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"sweepProtocolFees","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"IAdmin\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x7da00701c906b2b78d838eb9c510ab5903b6dd7f8e5fb12d4c4710c350e3c919\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://faff50fb8d1f3cf10122c1b611d0987ca58f4099d90c17163816c90d3077bce7\",\"dweb:/ipfs/QmWKF2L9D18J9QXiMbm6ucj3x8ebjQtTrycnkNmB4q3JRo\"]}},\"version\":1}"},"hashes":{"setChainGasAmount(uint256)":"b250fe6b","setProtocolFeeRate(uint256)":"b13aa2d6","sweepProtocolFees(address,address)":"06f333f2"}},"solidity/FastBridge.sol:IERC165":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Interface of the ERC-165 standard, as defined in the https://eips.ethereum.org/EIPS/eip-165[ERC]. Implementers can declare support of contract interfaces, which can then be queried by others ({ERC165Checker}). For an implementation, see {ERC165}.","kind":"dev","methods":{"supportsInterface(bytes4)":{"details":"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Interface of the ERC-165 standard, as defined in the https://eips.ethereum.org/EIPS/eip-165[ERC]. Implementers can declare support of contract interfaces, which can then be queried by others ({ERC165Checker}). For an implementation, see {ERC165}.\",\"kind\":\"dev\",\"methods\":{\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"IERC165\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x7da00701c906b2b78d838eb9c510ab5903b6dd7f8e5fb12d4c4710c350e3c919\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://faff50fb8d1f3cf10122c1b611d0987ca58f4099d90c17163816c90d3077bce7\",\"dweb:/ipfs/QmWKF2L9D18J9QXiMbm6ucj3x8ebjQtTrycnkNmB4q3JRo\"]}},\"version\":1}"},"hashes":{"supportsInterface(bytes4)":"01ffc9a7"}},"solidity/FastBridge.sol:IERC20":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Interface of the ERC-20 standard as defined in the ERC.","events":{"Approval(address,address,uint256)":{"details":"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance."},"Transfer(address,address,uint256)":{"details":"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero."}},"kind":"dev","methods":{"allowance(address,address)":{"details":"Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through {transferFrom}. This is zero by default. This value changes when {approve} or {transferFrom} are called."},"approve(address,uint256)":{"details":"Sets a `value` amount of tokens as the allowance of `spender` over the caller's tokens. Returns a boolean value indicating whether the operation succeeded. IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 Emits an {Approval} event."},"balanceOf(address)":{"details":"Returns the value of tokens owned by `account`."},"totalSupply()":{"details":"Returns the value of tokens in existence."},"transfer(address,uint256)":{"details":"Moves a `value` amount of tokens from the caller's account to `to`. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event."},"transferFrom(address,address,uint256)":{"details":"Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism. `value` is then deducted from the caller's allowance. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Interface of the ERC-20 standard as defined in the ERC.\",\"events\":{\"Approval(address,address,uint256)\":{\"details\":\"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance.\"},\"Transfer(address,address,uint256)\":{\"details\":\"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero.\"}},\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through {transferFrom}. This is zero by default. This value changes when {approve} or {transferFrom} are called.\"},\"approve(address,uint256)\":{\"details\":\"Sets a `value` amount of tokens as the allowance of `spender` over the caller's tokens. Returns a boolean value indicating whether the operation succeeded. IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 Emits an {Approval} event.\"},\"balanceOf(address)\":{\"details\":\"Returns the value of tokens owned by `account`.\"},\"totalSupply()\":{\"details\":\"Returns the value of tokens in existence.\"},\"transfer(address,uint256)\":{\"details\":\"Moves a `value` amount of tokens from the caller's account to `to`. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism. `value` is then deducted from the caller's allowance. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"IERC20\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x7da00701c906b2b78d838eb9c510ab5903b6dd7f8e5fb12d4c4710c350e3c919\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://faff50fb8d1f3cf10122c1b611d0987ca58f4099d90c17163816c90d3077bce7\",\"dweb:/ipfs/QmWKF2L9D18J9QXiMbm6ucj3x8ebjQtTrycnkNmB4q3JRo\"]}},\"version\":1}"},"hashes":{"allowance(address,address)":"dd62ed3e","approve(address,uint256)":"095ea7b3","balanceOf(address)":"70a08231","totalSupply()":"18160ddd","transfer(address,uint256)":"a9059cbb","transferFrom(address,address,uint256)":"23b872dd"}},"solidity/FastBridge.sol:IERC20Permit":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in https://eips.ethereum.org/EIPS/eip-2612[ERC-2612]. Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't need to send a transaction, and thus is not required to hold Ether at all. ==== Security Considerations There are two important considerations concerning the use of `permit`. The first is that a valid permit signature expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be considered as an intention to spend the allowance in any specific way. The second is that because permits have built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be generally recommended is: ```solidity function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} doThing(..., value); } function doThing(..., uint256 value) public { token.safeTransferFrom(msg.sender, address(this), value); ... } ``` Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also {SafeERC20-safeTransferFrom}). Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so contracts should have entry points that don't rely on permit.","kind":"dev","methods":{"DOMAIN_SEPARATOR()":{"details":"Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}."},"nonces(address)":{"details":"Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times."},"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)":{"details":"Sets `value` as the allowance of `spender` over ``owner``'s tokens, given ``owner``'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. CAUTION: See Security Considerations above."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in https://eips.ethereum.org/EIPS/eip-2612[ERC-2612]. Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't need to send a transaction, and thus is not required to hold Ether at all. ==== Security Considerations There are two important considerations concerning the use of `permit`. The first is that a valid permit signature expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be considered as an intention to spend the allowance in any specific way. The second is that because permits have built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be generally recommended is: ```solidity function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} doThing(..., value); } function doThing(..., uint256 value) public { token.safeTransferFrom(msg.sender, address(this), value); ... } ``` Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also {SafeERC20-safeTransferFrom}). Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so contracts should have entry points that don't rely on permit.\",\"kind\":\"dev\",\"methods\":{\"DOMAIN_SEPARATOR()\":{\"details\":\"Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\"},\"nonces(address)\":{\"details\":\"Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times.\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Sets `value` as the allowance of `spender` over ``owner``'s tokens, given ``owner``'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. CAUTION: See Security Considerations above.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"IERC20Permit\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x7da00701c906b2b78d838eb9c510ab5903b6dd7f8e5fb12d4c4710c350e3c919\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://faff50fb8d1f3cf10122c1b611d0987ca58f4099d90c17163816c90d3077bce7\",\"dweb:/ipfs/QmWKF2L9D18J9QXiMbm6ucj3x8ebjQtTrycnkNmB4q3JRo\"]}},\"version\":1}"},"hashes":{"DOMAIN_SEPARATOR()":"3644e515","nonces(address)":"7ecebe00","permit(address,address,uint256,uint256,uint8,bytes32,bytes32)":"d505accf"}},"solidity/FastBridge.sol:IFastBridge":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositRefunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"}],"name":"BridgeProofDisputed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":false,"internalType":"bytes32","name":"transactionHash","type":"bytes32"}],"name":"BridgeProofProvided","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint32","name":"originChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"chainGasAmount","type":"uint256"}],"name":"BridgeRelayed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes","name":"request","type":"bytes"},{"indexed":false,"internalType":"uint32","name":"destChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"sendChainGas","type":"bool"}],"name":"BridgeRequested","type":"event"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstChainId","type":"uint32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IFastBridge.BridgeParams","name":"params","type":"tuple"}],"name":"bridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"address","name":"relayer","type":"address"}],"name":"canClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"address","name":"to","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"dispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"getBridgeTransaction","outputs":[{"components":[{"internalType":"uint32","name":"originChainId","type":"uint32"},{"internalType":"uint32","name":"destChainId","type":"uint32"},{"internalType":"address","name":"originSender","type":"address"},{"internalType":"address","name":"destRecipient","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256","name":"originFeeAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct IFastBridge.BridgeTransaction","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"bytes32","name":"destTxHash","type":"bytes32"}],"name":"prove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"relay","outputs":[],"stateMutability":"payable","type":"function"}],"userDoc":{"kind":"user","methods":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"notice":"Initiates bridge on origin chain to be relayed by off-chain relayer"},"canClaim(bytes32,address)":{"notice":"Checks if the dispute period has passed so bridge deposit can be claimed"},"claim(bytes,address)":{"notice":"Completes bridge transaction on origin chain by claiming originally deposited capital"},"dispute(bytes32)":{"notice":"Disputes an outstanding proof in case relayer provided dest chain tx is invalid"},"getBridgeTransaction(bytes)":{"notice":"Decodes bridge request into a bridge transaction"},"prove(bytes,bytes32)":{"notice":"Provides proof on origin side that relayer provided funds on destination side of bridge transaction"},"refund(bytes)":{"notice":"Refunds an outstanding bridge transaction in case optimistic bridging failed"},"relay(bytes)":{"notice":"Relays destination side of bridge transaction by off-chain relayer"}},"version":1},"developerDoc":{"kind":"dev","methods":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"params":{"params":"The parameters required to bridge"}},"canClaim(bytes32,address)":{"params":{"relayer":"The address of the relayer attempting to claim","transactionId":"The transaction id associated with the encoded bridge transaction to check"}},"claim(bytes,address)":{"params":{"request":"The encoded bridge transaction to claim on origin chain","to":"The recipient address of the funds"}},"dispute(bytes32)":{"params":{"transactionId":"The transaction id associated with the encoded bridge transaction to dispute"}},"getBridgeTransaction(bytes)":{"params":{"request":"The bridge request to decode"}},"prove(bytes,bytes32)":{"params":{"destTxHash":"The destination tx hash proving bridge transaction was relayed","request":"The encoded bridge transaction to prove on origin chain"}},"refund(bytes)":{"params":{"request":"The encoded bridge transaction to refund"}},"relay(bytes)":{"params":{"request":"The encoded bridge transaction to relay on destination chain"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositRefunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"BridgeProofDisputed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"transactionHash\",\"type\":\"bytes32\"}],\"name\":\"BridgeProofProvided\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"BridgeRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"}],\"name\":\"BridgeRequested\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"bridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"canClaim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"dispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"getBridgeTransaction\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originSender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destRecipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originFeeAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeTransaction\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"destTxHash\",\"type\":\"bytes32\"}],\"name\":\"prove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"refund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"params\":{\"params\":\"The parameters required to bridge\"}},\"canClaim(bytes32,address)\":{\"params\":{\"relayer\":\"The address of the relayer attempting to claim\",\"transactionId\":\"The transaction id associated with the encoded bridge transaction to check\"}},\"claim(bytes,address)\":{\"params\":{\"request\":\"The encoded bridge transaction to claim on origin chain\",\"to\":\"The recipient address of the funds\"}},\"dispute(bytes32)\":{\"params\":{\"transactionId\":\"The transaction id associated with the encoded bridge transaction to dispute\"}},\"getBridgeTransaction(bytes)\":{\"params\":{\"request\":\"The bridge request to decode\"}},\"prove(bytes,bytes32)\":{\"params\":{\"destTxHash\":\"The destination tx hash proving bridge transaction was relayed\",\"request\":\"The encoded bridge transaction to prove on origin chain\"}},\"refund(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to refund\"}},\"relay(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to relay on destination chain\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"notice\":\"Initiates bridge on origin chain to be relayed by off-chain relayer\"},\"canClaim(bytes32,address)\":{\"notice\":\"Checks if the dispute period has passed so bridge deposit can be claimed\"},\"claim(bytes,address)\":{\"notice\":\"Completes bridge transaction on origin chain by claiming originally deposited capital\"},\"dispute(bytes32)\":{\"notice\":\"Disputes an outstanding proof in case relayer provided dest chain tx is invalid\"},\"getBridgeTransaction(bytes)\":{\"notice\":\"Decodes bridge request into a bridge transaction\"},\"prove(bytes,bytes32)\":{\"notice\":\"Provides proof on origin side that relayer provided funds on destination side of bridge transaction\"},\"refund(bytes)\":{\"notice\":\"Refunds an outstanding bridge transaction in case optimistic bridging failed\"},\"relay(bytes)\":{\"notice\":\"Relays destination side of bridge transaction by off-chain relayer\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"IFastBridge\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x7da00701c906b2b78d838eb9c510ab5903b6dd7f8e5fb12d4c4710c350e3c919\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://faff50fb8d1f3cf10122c1b611d0987ca58f4099d90c17163816c90d3077bce7\",\"dweb:/ipfs/QmWKF2L9D18J9QXiMbm6ucj3x8ebjQtTrycnkNmB4q3JRo\"]}},\"version\":1}"},"hashes":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":"45851694","canClaim(bytes32,address)":"aa9641ab","claim(bytes,address)":"41fcb612","dispute(bytes32)":"add98c70","getBridgeTransaction(bytes)":"ac11fb1a","prove(bytes,bytes32)":"886d36ff","refund(bytes)":"5eb7d946","relay(bytes)":"8f0d6f17"}},"solidity/FastBridge.sol:SafeERC20":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c6ed48084fea72d6c821edce7a5b7849414ac26c2e14da8d9184448698b54a2964736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c6ed48084fea72d6c821edce7a5b7849414ac26c2e14da8d9184448698b54a2964736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"39265:5019:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;39265:5019:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"39265:5019:0:-:0;;;;;;;;","abiDefinition":[{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"currentAllowance","type":"uint256"},{"internalType":"uint256","name":"requestedDecrease","type":"uint256"}],"name":"SafeERC20FailedDecreaseAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Wrappers around ERC-20 operations that throw on failure (when the token contract returns false). Tokens that return no value (and instead revert or throw on failure) are also supported, non-reverting calls are assumed to be successful. To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, which allows you to call the safe operations as `token.safeTransfer(...)`, etc.","errors":{"SafeERC20FailedDecreaseAllowance(address,uint256,uint256)":[{"details":"Indicates a failed `decreaseAllowance` request."}],"SafeERC20FailedOperation(address)":[{"details":"An operation with an ERC-20 token failed."}]},"kind":"dev","methods":{},"title":"SafeERC20","version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"currentAllowance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestedDecrease\",\"type\":\"uint256\"}],\"name\":\"SafeERC20FailedDecreaseAllowance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"}],\"devdoc\":{\"details\":\"Wrappers around ERC-20 operations that throw on failure (when the token contract returns false). Tokens that return no value (and instead revert or throw on failure) are also supported, non-reverting calls are assumed to be successful. To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\",\"errors\":{\"SafeERC20FailedDecreaseAllowance(address,uint256,uint256)\":[{\"details\":\"Indicates a failed `decreaseAllowance` request.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}]},\"kind\":\"dev\",\"methods\":{},\"title\":\"SafeERC20\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"SafeERC20\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x7da00701c906b2b78d838eb9c510ab5903b6dd7f8e5fb12d4c4710c350e3c919\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://faff50fb8d1f3cf10122c1b611d0987ca58f4099d90c17163816c90d3077bce7\",\"dweb:/ipfs/QmWKF2L9D18J9QXiMbm6ucj3x8ebjQtTrycnkNmB4q3JRo\"]}},\"version\":1}"},"hashes":{}},"solidity/FastBridge.sol:UniversalTokenLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122054dc3657c8fde761d2c05cf2a9b92991c4c740565f4124cc2177c16ea935345764736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122054dc3657c8fde761d2c05cf2a9b92991c4c740565f4124cc2177c16ea935345764736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"51225:2551:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;51225:2551:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"51225:2551:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridge.sol\":\"UniversalTokenLib\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridge.sol\":{\"keccak256\":\"0x7da00701c906b2b78d838eb9c510ab5903b6dd7f8e5fb12d4c4710c350e3c919\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://faff50fb8d1f3cf10122c1b611d0987ca58f4099d90c17163816c90d3077bce7\",\"dweb:/ipfs/QmWKF2L9D18J9QXiMbm6ucj3x8ebjQtTrycnkNmB4q3JRo\"]}},\"version\":1}"},"hashes":{}}} \ No newline at end of file diff --git a/services/rfq/contracts/testcontracts/fastbridgemock/fastbridgemock.abigen.go b/services/rfq/contracts/testcontracts/fastbridgemock/fastbridgemock.abigen.go index a78cf75858..bd92907a76 100644 --- a/services/rfq/contracts/testcontracts/fastbridgemock/fastbridgemock.abigen.go +++ b/services/rfq/contracts/testcontracts/fastbridgemock/fastbridgemock.abigen.go @@ -895,135 +895,128 @@ func (_AccessControl *AccessControlFilterer) ParseRoleRevoked(log types.Log) (*A return event, nil } -// AddressMetaData contains all meta data concerning the Address contract. -var AddressMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"}]", - Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122017364e1ba957198b5cc9fefb513c6037bd8284eb81dd4aa2302b849eec9d9d5364736f6c63430008140033", +// AccessControlEnumerableMetaData contains all meta data concerning the AccessControlEnumerable contract. +var AccessControlEnumerableMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "a217fddf": "DEFAULT_ADMIN_ROLE()", + "248a9ca3": "getRoleAdmin(bytes32)", + "9010d07c": "getRoleMember(bytes32,uint256)", + "ca15c873": "getRoleMemberCount(bytes32)", + "2f2ff15d": "grantRole(bytes32,address)", + "91d14854": "hasRole(bytes32,address)", + "36568abe": "renounceRole(bytes32,address)", + "d547741f": "revokeRole(bytes32,address)", + "01ffc9a7": "supportsInterface(bytes4)", + }, } -// AddressABI is the input ABI used to generate the binding from. -// Deprecated: Use AddressMetaData.ABI instead. -var AddressABI = AddressMetaData.ABI - -// AddressBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use AddressMetaData.Bin instead. -var AddressBin = AddressMetaData.Bin - -// DeployAddress deploys a new Ethereum contract, binding an instance of Address to it. -func DeployAddress(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Address, error) { - parsed, err := AddressMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } +// AccessControlEnumerableABI is the input ABI used to generate the binding from. +// Deprecated: Use AccessControlEnumerableMetaData.ABI instead. +var AccessControlEnumerableABI = AccessControlEnumerableMetaData.ABI - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(AddressBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Address{AddressCaller: AddressCaller{contract: contract}, AddressTransactor: AddressTransactor{contract: contract}, AddressFilterer: AddressFilterer{contract: contract}}, nil -} +// Deprecated: Use AccessControlEnumerableMetaData.Sigs instead. +// AccessControlEnumerableFuncSigs maps the 4-byte function signature to its string representation. +var AccessControlEnumerableFuncSigs = AccessControlEnumerableMetaData.Sigs -// Address is an auto generated Go binding around an Ethereum contract. -type Address struct { - AddressCaller // Read-only binding to the contract - AddressTransactor // Write-only binding to the contract - AddressFilterer // Log filterer for contract events +// AccessControlEnumerable is an auto generated Go binding around an Ethereum contract. +type AccessControlEnumerable struct { + AccessControlEnumerableCaller // Read-only binding to the contract + AccessControlEnumerableTransactor // Write-only binding to the contract + AccessControlEnumerableFilterer // Log filterer for contract events } -// AddressCaller is an auto generated read-only Go binding around an Ethereum contract. -type AddressCaller struct { +// AccessControlEnumerableCaller is an auto generated read-only Go binding around an Ethereum contract. +type AccessControlEnumerableCaller struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// AddressTransactor is an auto generated write-only Go binding around an Ethereum contract. -type AddressTransactor struct { +// AccessControlEnumerableTransactor is an auto generated write-only Go binding around an Ethereum contract. +type AccessControlEnumerableTransactor struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// AddressFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type AddressFilterer struct { +// AccessControlEnumerableFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type AccessControlEnumerableFilterer struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// AddressSession is an auto generated Go binding around an Ethereum contract, +// AccessControlEnumerableSession is an auto generated Go binding around an Ethereum contract, // with pre-set call and transact options. -type AddressSession struct { - Contract *Address // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +type AccessControlEnumerableSession struct { + Contract *AccessControlEnumerable // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// AddressCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// AccessControlEnumerableCallerSession is an auto generated read-only Go binding around an Ethereum contract, // with pre-set call options. -type AddressCallerSession struct { - Contract *AddressCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session +type AccessControlEnumerableCallerSession struct { + Contract *AccessControlEnumerableCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session } -// AddressTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// AccessControlEnumerableTransactorSession is an auto generated write-only Go binding around an Ethereum contract, // with pre-set transact options. -type AddressTransactorSession struct { - Contract *AddressTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +type AccessControlEnumerableTransactorSession struct { + Contract *AccessControlEnumerableTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// AddressRaw is an auto generated low-level Go binding around an Ethereum contract. -type AddressRaw struct { - Contract *Address // Generic contract binding to access the raw methods on +// AccessControlEnumerableRaw is an auto generated low-level Go binding around an Ethereum contract. +type AccessControlEnumerableRaw struct { + Contract *AccessControlEnumerable // Generic contract binding to access the raw methods on } -// AddressCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type AddressCallerRaw struct { - Contract *AddressCaller // Generic read-only contract binding to access the raw methods on +// AccessControlEnumerableCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type AccessControlEnumerableCallerRaw struct { + Contract *AccessControlEnumerableCaller // Generic read-only contract binding to access the raw methods on } -// AddressTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type AddressTransactorRaw struct { - Contract *AddressTransactor // Generic write-only contract binding to access the raw methods on +// AccessControlEnumerableTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type AccessControlEnumerableTransactorRaw struct { + Contract *AccessControlEnumerableTransactor // Generic write-only contract binding to access the raw methods on } -// NewAddress creates a new instance of Address, bound to a specific deployed contract. -func NewAddress(address common.Address, backend bind.ContractBackend) (*Address, error) { - contract, err := bindAddress(address, backend, backend, backend) +// NewAccessControlEnumerable creates a new instance of AccessControlEnumerable, bound to a specific deployed contract. +func NewAccessControlEnumerable(address common.Address, backend bind.ContractBackend) (*AccessControlEnumerable, error) { + contract, err := bindAccessControlEnumerable(address, backend, backend, backend) if err != nil { return nil, err } - return &Address{AddressCaller: AddressCaller{contract: contract}, AddressTransactor: AddressTransactor{contract: contract}, AddressFilterer: AddressFilterer{contract: contract}}, nil + return &AccessControlEnumerable{AccessControlEnumerableCaller: AccessControlEnumerableCaller{contract: contract}, AccessControlEnumerableTransactor: AccessControlEnumerableTransactor{contract: contract}, AccessControlEnumerableFilterer: AccessControlEnumerableFilterer{contract: contract}}, nil } -// NewAddressCaller creates a new read-only instance of Address, bound to a specific deployed contract. -func NewAddressCaller(address common.Address, caller bind.ContractCaller) (*AddressCaller, error) { - contract, err := bindAddress(address, caller, nil, nil) +// NewAccessControlEnumerableCaller creates a new read-only instance of AccessControlEnumerable, bound to a specific deployed contract. +func NewAccessControlEnumerableCaller(address common.Address, caller bind.ContractCaller) (*AccessControlEnumerableCaller, error) { + contract, err := bindAccessControlEnumerable(address, caller, nil, nil) if err != nil { return nil, err } - return &AddressCaller{contract: contract}, nil + return &AccessControlEnumerableCaller{contract: contract}, nil } -// NewAddressTransactor creates a new write-only instance of Address, bound to a specific deployed contract. -func NewAddressTransactor(address common.Address, transactor bind.ContractTransactor) (*AddressTransactor, error) { - contract, err := bindAddress(address, nil, transactor, nil) +// NewAccessControlEnumerableTransactor creates a new write-only instance of AccessControlEnumerable, bound to a specific deployed contract. +func NewAccessControlEnumerableTransactor(address common.Address, transactor bind.ContractTransactor) (*AccessControlEnumerableTransactor, error) { + contract, err := bindAccessControlEnumerable(address, nil, transactor, nil) if err != nil { return nil, err } - return &AddressTransactor{contract: contract}, nil + return &AccessControlEnumerableTransactor{contract: contract}, nil } -// NewAddressFilterer creates a new log filterer instance of Address, bound to a specific deployed contract. -func NewAddressFilterer(address common.Address, filterer bind.ContractFilterer) (*AddressFilterer, error) { - contract, err := bindAddress(address, nil, nil, filterer) +// NewAccessControlEnumerableFilterer creates a new log filterer instance of AccessControlEnumerable, bound to a specific deployed contract. +func NewAccessControlEnumerableFilterer(address common.Address, filterer bind.ContractFilterer) (*AccessControlEnumerableFilterer, error) { + contract, err := bindAccessControlEnumerable(address, nil, nil, filterer) if err != nil { return nil, err } - return &AddressFilterer{contract: contract}, nil + return &AccessControlEnumerableFilterer{contract: contract}, nil } -// bindAddress binds a generic wrapper to an already deployed contract. -func bindAddress(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := AddressMetaData.GetAbi() +// bindAccessControlEnumerable binds a generic wrapper to an already deployed contract. +func bindAccessControlEnumerable(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := AccessControlEnumerableMetaData.GetAbi() if err != nil { return nil, err } @@ -1034,870 +1027,616 @@ func bindAddress(address common.Address, caller bind.ContractCaller, transactor // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. -func (_Address *AddressRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Address.Contract.AddressCaller.contract.Call(opts, result, method, params...) +func (_AccessControlEnumerable *AccessControlEnumerableRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AccessControlEnumerable.Contract.AccessControlEnumerableCaller.contract.Call(opts, result, method, params...) } // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. -func (_Address *AddressRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Address.Contract.AddressTransactor.contract.Transfer(opts) +func (_AccessControlEnumerable *AccessControlEnumerableRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.AccessControlEnumerableTransactor.contract.Transfer(opts) } // Transact invokes the (paid) contract method with params as input values. -func (_Address *AddressRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Address.Contract.AddressTransactor.contract.Transact(opts, method, params...) +func (_AccessControlEnumerable *AccessControlEnumerableRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.AccessControlEnumerableTransactor.contract.Transact(opts, method, params...) } // Call invokes the (constant) contract method with params as input values and // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. -func (_Address *AddressCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Address.Contract.contract.Call(opts, result, method, params...) +func (_AccessControlEnumerable *AccessControlEnumerableCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AccessControlEnumerable.Contract.contract.Call(opts, result, method, params...) } // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. -func (_Address *AddressTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Address.Contract.contract.Transfer(opts) +func (_AccessControlEnumerable *AccessControlEnumerableTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.contract.Transfer(opts) } // Transact invokes the (paid) contract method with params as input values. -func (_Address *AddressTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Address.Contract.contract.Transact(opts, method, params...) -} - -// AdminMetaData contains all meta data concerning the Admin contract. -var AdminMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"addGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"addGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"addRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"removeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"removeGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"removeRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Sigs: map[string]string{ - "a217fddf": "DEFAULT_ADMIN_ROLE()", - "bf333f2c": "FEE_BPS()", - "0f5f6ed7": "FEE_RATE_MAX()", - "ccc57490": "GOVERNOR_ROLE()", - "03ed0ee5": "GUARD_ROLE()", - "926d7d7f": "RELAYER_ROLE()", - "3c4a25d0": "addGovernor(address)", - "6913a63c": "addGuard(address)", - "dd39f00d": "addRelayer(address)", - "e00a83e0": "chainGasAmount()", - "248a9ca3": "getRoleAdmin(bytes32)", - "2f2ff15d": "grantRole(bytes32,address)", - "91d14854": "hasRole(bytes32,address)", - "58f85880": "protocolFeeRate()", - "dcf844a7": "protocolFees(address)", - "eecdac88": "removeGovernor(address)", - "b6235016": "removeGuard(address)", - "60f0a5ac": "removeRelayer(address)", - "36568abe": "renounceRole(bytes32,address)", - "d547741f": "revokeRole(bytes32,address)", - "b250fe6b": "setChainGasAmount(uint256)", - "b13aa2d6": "setProtocolFeeRate(uint256)", - "01ffc9a7": "supportsInterface(bytes4)", - "06f333f2": "sweepProtocolFees(address,address)", - }, - Bin: "0x608060405234801561001057600080fd5b50604051620015cf380380620015cf833981016040819052610031916100ef565b61003c600082610043565b505061011f565b6000828152602081815260408083206001600160a01b038516845290915281205460ff166100e5576000838152602081815260408083206001600160a01b03861684529091529020805460ff1916600117905561009d3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016100e9565b5060005b92915050565b60006020828403121561010157600080fd5b81516001600160a01b038116811461011857600080fd5b9392505050565b6114a0806200012f6000396000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c8063926d7d7f116100e3578063ccc574901161008c578063dd39f00d11610066578063dd39f00d146103b3578063e00a83e0146103c6578063eecdac88146103cf57600080fd5b8063ccc5749014610359578063d547741f14610380578063dcf844a71461039357600080fd5b8063b250fe6b116100bd578063b250fe6b14610329578063b62350161461033c578063bf333f2c1461034f57600080fd5b8063926d7d7f146102e7578063a217fddf1461030e578063b13aa2d61461031657600080fd5b806336568abe1161014557806360f0a5ac1161011f57806360f0a5ac1461027d5780636913a63c1461029057806391d14854146102a357600080fd5b806336568abe1461024e5780633c4a25d01461026157806358f858801461027457600080fd5b80630f5f6ed7116101765780630f5f6ed71461020f578063248a9ca3146102185780632f2ff15d1461023b57600080fd5b806301ffc9a71461019d57806303ed0ee5146101c557806306f333f2146101fa575b600080fd5b6101b06101ab366004611324565b6103e2565b60405190151581526020015b60405180910390f35b6101ec7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b6040519081526020016101bc565b61020d61020836600461138f565b61047b565b005b6101ec61271081565b6101ec6102263660046113c2565b60009081526020819052604090206001015490565b61020d6102493660046113db565b6105da565b61020d61025c3660046113db565b610605565b61020d61026f3660046113fe565b610663565b6101ec60015481565b61020d61028b3660046113fe565b610716565b61020d61029e3660046113fe565b6107c2565b6101b06102b13660046113db565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6101ec7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b6101ec600081565b61020d6103243660046113c2565b61086e565b61020d6103373660046113c2565b6109b8565b61020d61034a3660046113fe565b610a8e565b6101ec620f424081565b6101ec7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b61020d61038e3660046113db565b610b3a565b6101ec6103a13660046113fe565b60026020526000908152604090205481565b61020d6103c13660046113fe565b610b5f565b6101ec60035481565b61020d6103dd3660046113fe565b610c0b565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061047557507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16610518576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600260205260408120549081900361054b57505050565b73ffffffffffffffffffffffffffffffffffffffff831660008181526002602052604081205561057c908383610cb7565b6040805173ffffffffffffffffffffffffffffffffffffffff8086168252841660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b5050565b6000828152602081905260409020600101546105f581610e0e565b6105ff8383610e1b565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610654576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61065e8282610f17565b505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661069e57600080fd5b6106c87f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5582610e1b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5906020015b60405180910390a150565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661075157600080fd5b61077b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc482610f17565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b9060200161070b565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166107fd57600080fd5b6108277f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d82610e1b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f599060200161070b565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16610906576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f720000000000000000604482015260640161050f565b612710811115610972576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d617800000000000000000000000000000000604482015260640161050f565b600180549082905560408051828152602081018490527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a15050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16610a50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f720000000000000000604482015260640161050f565b600380549082905560408051828152602081018490527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa91016109ac565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610ac957600080fd5b610af37f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d82610f17565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d0489060200161070b565b600082815260208190526040902060010154610b5581610e0e565b6105ff8383610f17565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610b9a57600080fd5b610bc47fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc482610e1b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c59060200161070b565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610c4657600080fd5b610c707f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5582610f17565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b9060200161070b565b3073ffffffffffffffffffffffffffffffffffffffff831603610cd957505050565b80600003610ce657505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff841601610ded5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610d7d576040519150601f19603f3d011682016040523d82523d6000602084013e610d82565b606091505b50509050806105ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c656400000000000000000000000000604482015260640161050f565b61065e73ffffffffffffffffffffffffffffffffffffffff84168383610fd2565b610e18813361105f565b50565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16610f0f5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610ead3390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610475565b506000610475565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff1615610f0f5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610475565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261065e9084906110e5565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166105d6576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024810183905260440161050f565b600061110773ffffffffffffffffffffffffffffffffffffffff84168361117b565b9050805160001415801561112c57508080602001905181019061112a9190611419565b155b1561065e576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161050f565b606061118983836000611190565b9392505050565b6060814710156111ce576040517fcd78605900000000000000000000000000000000000000000000000000000000815230600482015260240161050f565b6000808573ffffffffffffffffffffffffffffffffffffffff1684866040516111f7919061143b565b60006040518083038185875af1925050503d8060008114611234576040519150601f19603f3d011682016040523d82523d6000602084013e611239565b606091505b5091509150611249868383611253565b9695505050505050565b60608261126857611263826112e2565b611189565b815115801561128c575073ffffffffffffffffffffffffffffffffffffffff84163b155b156112db576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015260240161050f565b5080611189565b8051156112f25780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561133657600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461118957600080fd5b803573ffffffffffffffffffffffffffffffffffffffff8116811461138a57600080fd5b919050565b600080604083850312156113a257600080fd5b6113ab83611366565b91506113b960208401611366565b90509250929050565b6000602082840312156113d457600080fd5b5035919050565b600080604083850312156113ee57600080fd5b823591506113b960208401611366565b60006020828403121561141057600080fd5b61118982611366565b60006020828403121561142b57600080fd5b8151801515811461118957600080fd5b6000825160005b8181101561145c5760208186018101518583015201611442565b50600092019182525091905056fea26469706673582212205c49afb355dff0d97bec5b816fcda1abe23f00447ca3f7d7a753997929922bba64736f6c63430008140033", +func (_AccessControlEnumerable *AccessControlEnumerableTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.contract.Transact(opts, method, params...) } -// AdminABI is the input ABI used to generate the binding from. -// Deprecated: Use AdminMetaData.ABI instead. -var AdminABI = AdminMetaData.ABI - -// Deprecated: Use AdminMetaData.Sigs instead. -// AdminFuncSigs maps the 4-byte function signature to its string representation. -var AdminFuncSigs = AdminMetaData.Sigs - -// AdminBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use AdminMetaData.Bin instead. -var AdminBin = AdminMetaData.Bin +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_AccessControlEnumerable *AccessControlEnumerableCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _AccessControlEnumerable.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") -// DeployAdmin deploys a new Ethereum contract, binding an instance of Admin to it. -func DeployAdmin(auth *bind.TransactOpts, backend bind.ContractBackend, _owner common.Address) (common.Address, *types.Transaction, *Admin, error) { - parsed, err := AdminMetaData.GetAbi() if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") + return *new([32]byte), err } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(AdminBin), backend, _owner) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Admin{AdminCaller: AdminCaller{contract: contract}, AdminTransactor: AdminTransactor{contract: contract}, AdminFilterer: AdminFilterer{contract: contract}}, nil -} + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) -// Admin is an auto generated Go binding around an Ethereum contract. -type Admin struct { - AdminCaller // Read-only binding to the contract - AdminTransactor // Write-only binding to the contract - AdminFilterer // Log filterer for contract events -} + return out0, err -// AdminCaller is an auto generated read-only Go binding around an Ethereum contract. -type AdminCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// AdminTransactor is an auto generated write-only Go binding around an Ethereum contract. -type AdminTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_AccessControlEnumerable *AccessControlEnumerableSession) DEFAULTADMINROLE() ([32]byte, error) { + return _AccessControlEnumerable.Contract.DEFAULTADMINROLE(&_AccessControlEnumerable.CallOpts) } -// AdminFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type AdminFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_AccessControlEnumerable *AccessControlEnumerableCallerSession) DEFAULTADMINROLE() ([32]byte, error) { + return _AccessControlEnumerable.Contract.DEFAULTADMINROLE(&_AccessControlEnumerable.CallOpts) } -// AdminSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type AdminSession struct { - Contract *Admin // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_AccessControlEnumerable *AccessControlEnumerableCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { + var out []interface{} + err := _AccessControlEnumerable.contract.Call(opts, &out, "getRoleAdmin", role) -// AdminCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type AdminCallerSession struct { - Contract *AdminCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} + if err != nil { + return *new([32]byte), err + } -// AdminTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type AdminTransactorSession struct { - Contract *AdminTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err -// AdminRaw is an auto generated low-level Go binding around an Ethereum contract. -type AdminRaw struct { - Contract *Admin // Generic contract binding to access the raw methods on } -// AdminCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type AdminCallerRaw struct { - Contract *AdminCaller // Generic read-only contract binding to access the raw methods on +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_AccessControlEnumerable *AccessControlEnumerableSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _AccessControlEnumerable.Contract.GetRoleAdmin(&_AccessControlEnumerable.CallOpts, role) } -// AdminTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type AdminTransactorRaw struct { - Contract *AdminTransactor // Generic write-only contract binding to access the raw methods on +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_AccessControlEnumerable *AccessControlEnumerableCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _AccessControlEnumerable.Contract.GetRoleAdmin(&_AccessControlEnumerable.CallOpts, role) } -// NewAdmin creates a new instance of Admin, bound to a specific deployed contract. -func NewAdmin(address common.Address, backend bind.ContractBackend) (*Admin, error) { - contract, err := bindAdmin(address, backend, backend, backend) +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. +// +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_AccessControlEnumerable *AccessControlEnumerableCaller) GetRoleMember(opts *bind.CallOpts, role [32]byte, index *big.Int) (common.Address, error) { + var out []interface{} + err := _AccessControlEnumerable.contract.Call(opts, &out, "getRoleMember", role, index) + if err != nil { - return nil, err + return *new(common.Address), err } - return &Admin{AdminCaller: AdminCaller{contract: contract}, AdminTransactor: AdminTransactor{contract: contract}, AdminFilterer: AdminFilterer{contract: contract}}, nil + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + } -// NewAdminCaller creates a new read-only instance of Admin, bound to a specific deployed contract. -func NewAdminCaller(address common.Address, caller bind.ContractCaller) (*AdminCaller, error) { - contract, err := bindAdmin(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &AdminCaller{contract: contract}, nil +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. +// +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_AccessControlEnumerable *AccessControlEnumerableSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _AccessControlEnumerable.Contract.GetRoleMember(&_AccessControlEnumerable.CallOpts, role, index) } -// NewAdminTransactor creates a new write-only instance of Admin, bound to a specific deployed contract. -func NewAdminTransactor(address common.Address, transactor bind.ContractTransactor) (*AdminTransactor, error) { - contract, err := bindAdmin(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &AdminTransactor{contract: contract}, nil +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. +// +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_AccessControlEnumerable *AccessControlEnumerableCallerSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _AccessControlEnumerable.Contract.GetRoleMember(&_AccessControlEnumerable.CallOpts, role, index) } -// NewAdminFilterer creates a new log filterer instance of Admin, bound to a specific deployed contract. -func NewAdminFilterer(address common.Address, filterer bind.ContractFilterer) (*AdminFilterer, error) { - contract, err := bindAdmin(address, nil, nil, filterer) +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. +// +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_AccessControlEnumerable *AccessControlEnumerableCaller) GetRoleMemberCount(opts *bind.CallOpts, role [32]byte) (*big.Int, error) { + var out []interface{} + err := _AccessControlEnumerable.contract.Call(opts, &out, "getRoleMemberCount", role) + if err != nil { - return nil, err + return *new(*big.Int), err } - return &AdminFilterer{contract: contract}, nil -} - -// bindAdmin binds a generic wrapper to an already deployed contract. -func bindAdmin(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := AdminMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Admin *AdminRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Admin.Contract.AdminCaller.contract.Call(opts, result, method, params...) -} -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Admin *AdminRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Admin.Contract.AdminTransactor.contract.Transfer(opts) -} + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) -// Transact invokes the (paid) contract method with params as input values. -func (_Admin *AdminRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Admin.Contract.AdminTransactor.contract.Transact(opts, method, params...) -} + return out0, err -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Admin *AdminCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Admin.Contract.contract.Call(opts, result, method, params...) } -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Admin *AdminTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Admin.Contract.contract.Transfer(opts) +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. +// +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_AccessControlEnumerable *AccessControlEnumerableSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _AccessControlEnumerable.Contract.GetRoleMemberCount(&_AccessControlEnumerable.CallOpts, role) } -// Transact invokes the (paid) contract method with params as input values. -func (_Admin *AdminTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Admin.Contract.contract.Transact(opts, method, params...) +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. +// +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_AccessControlEnumerable *AccessControlEnumerableCallerSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _AccessControlEnumerable.Contract.GetRoleMemberCount(&_AccessControlEnumerable.CallOpts, role) } -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// HasRole is a free data retrieval call binding the contract method 0x91d14854. // -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_Admin *AdminCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_AccessControlEnumerable *AccessControlEnumerableCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { var out []interface{} - err := _Admin.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") + err := _AccessControlEnumerable.contract.Call(opts, &out, "hasRole", role, account) if err != nil { - return *new([32]byte), err + return *new(bool), err } - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) return out0, err } -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// HasRole is a free data retrieval call binding the contract method 0x91d14854. // -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_Admin *AdminSession) DEFAULTADMINROLE() ([32]byte, error) { - return _Admin.Contract.DEFAULTADMINROLE(&_Admin.CallOpts) +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_AccessControlEnumerable *AccessControlEnumerableSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _AccessControlEnumerable.Contract.HasRole(&_AccessControlEnumerable.CallOpts, role, account) } -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// HasRole is a free data retrieval call binding the contract method 0x91d14854. // -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_Admin *AdminCallerSession) DEFAULTADMINROLE() ([32]byte, error) { - return _Admin.Contract.DEFAULTADMINROLE(&_Admin.CallOpts) +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_AccessControlEnumerable *AccessControlEnumerableCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _AccessControlEnumerable.Contract.HasRole(&_AccessControlEnumerable.CallOpts, role, account) } -// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: function FEE_BPS() view returns(uint256) -func (_Admin *AdminCaller) FEEBPS(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_AccessControlEnumerable *AccessControlEnumerableCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { var out []interface{} - err := _Admin.contract.Call(opts, &out, "FEE_BPS") + err := _AccessControlEnumerable.contract.Call(opts, &out, "supportsInterface", interfaceId) if err != nil { - return *new(*big.Int), err + return *new(bool), err } - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) return out0, err } -// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: function FEE_BPS() view returns(uint256) -func (_Admin *AdminSession) FEEBPS() (*big.Int, error) { - return _Admin.Contract.FEEBPS(&_Admin.CallOpts) +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_AccessControlEnumerable *AccessControlEnumerableSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _AccessControlEnumerable.Contract.SupportsInterface(&_AccessControlEnumerable.CallOpts, interfaceId) } -// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: function FEE_BPS() view returns(uint256) -func (_Admin *AdminCallerSession) FEEBPS() (*big.Int, error) { - return _Admin.Contract.FEEBPS(&_Admin.CallOpts) +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_AccessControlEnumerable *AccessControlEnumerableCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _AccessControlEnumerable.Contract.SupportsInterface(&_AccessControlEnumerable.CallOpts, interfaceId) } -// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. // -// Solidity: function FEE_RATE_MAX() view returns(uint256) -func (_Admin *AdminCaller) FEERATEMAX(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "FEE_RATE_MAX") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_AccessControlEnumerable *AccessControlEnumerableTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _AccessControlEnumerable.contract.Transact(opts, "grantRole", role, account) } -// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. // -// Solidity: function FEE_RATE_MAX() view returns(uint256) -func (_Admin *AdminSession) FEERATEMAX() (*big.Int, error) { - return _Admin.Contract.FEERATEMAX(&_Admin.CallOpts) +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_AccessControlEnumerable *AccessControlEnumerableSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.GrantRole(&_AccessControlEnumerable.TransactOpts, role, account) } -// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. // -// Solidity: function FEE_RATE_MAX() view returns(uint256) -func (_Admin *AdminCallerSession) FEERATEMAX() (*big.Int, error) { - return _Admin.Contract.FEERATEMAX(&_Admin.CallOpts) +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_AccessControlEnumerable *AccessControlEnumerableTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.GrantRole(&_AccessControlEnumerable.TransactOpts, role, account) } -// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. // -// Solidity: function GOVERNOR_ROLE() view returns(bytes32) -func (_Admin *AdminCaller) GOVERNORROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "GOVERNOR_ROLE") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_AccessControlEnumerable *AccessControlEnumerableTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _AccessControlEnumerable.contract.Transact(opts, "renounceRole", role, callerConfirmation) } -// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. // -// Solidity: function GOVERNOR_ROLE() view returns(bytes32) -func (_Admin *AdminSession) GOVERNORROLE() ([32]byte, error) { - return _Admin.Contract.GOVERNORROLE(&_Admin.CallOpts) +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_AccessControlEnumerable *AccessControlEnumerableSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.RenounceRole(&_AccessControlEnumerable.TransactOpts, role, callerConfirmation) } -// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. // -// Solidity: function GOVERNOR_ROLE() view returns(bytes32) -func (_Admin *AdminCallerSession) GOVERNORROLE() ([32]byte, error) { - return _Admin.Contract.GOVERNORROLE(&_Admin.CallOpts) +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_AccessControlEnumerable *AccessControlEnumerableTransactorSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.RenounceRole(&_AccessControlEnumerable.TransactOpts, role, callerConfirmation) } -// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. // -// Solidity: function GUARD_ROLE() view returns(bytes32) -func (_Admin *AdminCaller) GUARDROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "GUARD_ROLE") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_AccessControlEnumerable *AccessControlEnumerableTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _AccessControlEnumerable.contract.Transact(opts, "revokeRole", role, account) } -// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. // -// Solidity: function GUARD_ROLE() view returns(bytes32) -func (_Admin *AdminSession) GUARDROLE() ([32]byte, error) { - return _Admin.Contract.GUARDROLE(&_Admin.CallOpts) +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_AccessControlEnumerable *AccessControlEnumerableSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.RevokeRole(&_AccessControlEnumerable.TransactOpts, role, account) } -// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. // -// Solidity: function GUARD_ROLE() view returns(bytes32) -func (_Admin *AdminCallerSession) GUARDROLE() ([32]byte, error) { - return _Admin.Contract.GUARDROLE(&_Admin.CallOpts) +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_AccessControlEnumerable *AccessControlEnumerableTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _AccessControlEnumerable.Contract.RevokeRole(&_AccessControlEnumerable.TransactOpts, role, account) } -// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. -// -// Solidity: function RELAYER_ROLE() view returns(bytes32) -func (_Admin *AdminCaller) RELAYERROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "RELAYER_ROLE") +// AccessControlEnumerableRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the AccessControlEnumerable contract. +type AccessControlEnumerableRoleAdminChangedIterator struct { + Event *AccessControlEnumerableRoleAdminChanged // Event containing the contract specifics and raw log - if err != nil { - return *new([32]byte), err + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AccessControlEnumerableRoleAdminChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(AccessControlEnumerableRoleAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(AccessControlEnumerableRoleAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true - return out0, err + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} +// Error returns any retrieval or parsing error occurred during filtering. +func (it *AccessControlEnumerableRoleAdminChangedIterator) Error() error { + return it.fail } -// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. -// -// Solidity: function RELAYER_ROLE() view returns(bytes32) -func (_Admin *AdminSession) RELAYERROLE() ([32]byte, error) { - return _Admin.Contract.RELAYERROLE(&_Admin.CallOpts) +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AccessControlEnumerableRoleAdminChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil } -// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. -// -// Solidity: function RELAYER_ROLE() view returns(bytes32) -func (_Admin *AdminCallerSession) RELAYERROLE() ([32]byte, error) { - return _Admin.Contract.RELAYERROLE(&_Admin.CallOpts) +// AccessControlEnumerableRoleAdminChanged represents a RoleAdminChanged event raised by the AccessControlEnumerable contract. +type AccessControlEnumerableRoleAdminChanged struct { + Role [32]byte + PreviousAdminRole [32]byte + NewAdminRole [32]byte + Raw types.Log // Blockchain specific contextual infos } -// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. +// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. // -// Solidity: function chainGasAmount() view returns(uint256) -func (_Admin *AdminCaller) ChainGasAmount(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "chainGasAmount") +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_AccessControlEnumerable *AccessControlEnumerableFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*AccessControlEnumerableRoleAdminChangedIterator, error) { - if err != nil { - return *new(*big.Int), err + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) } - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. -// -// Solidity: function chainGasAmount() view returns(uint256) -func (_Admin *AdminSession) ChainGasAmount() (*big.Int, error) { - return _Admin.Contract.ChainGasAmount(&_Admin.CallOpts) + logs, sub, err := _AccessControlEnumerable.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) + if err != nil { + return nil, err + } + return &AccessControlEnumerableRoleAdminChangedIterator{contract: _AccessControlEnumerable.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil } -// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. +// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. // -// Solidity: function chainGasAmount() view returns(uint256) -func (_Admin *AdminCallerSession) ChainGasAmount() (*big.Int, error) { - return _Admin.Contract.ChainGasAmount(&_Admin.CallOpts) -} +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_AccessControlEnumerable *AccessControlEnumerableFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *AccessControlEnumerableRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_Admin *AdminCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "getRoleAdmin", role) + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + } + logs, sub, err := _AccessControlEnumerable.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { - return *new([32]byte), err + return nil, err } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(AccessControlEnumerableRoleAdminChanged) + if err := _AccessControlEnumerable.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { + return err + } + event.Raw = log - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil } -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. // -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_Admin *AdminSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { - return _Admin.Contract.GetRoleAdmin(&_Admin.CallOpts, role) +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_AccessControlEnumerable *AccessControlEnumerableFilterer) ParseRoleAdminChanged(log types.Log) (*AccessControlEnumerableRoleAdminChanged, error) { + event := new(AccessControlEnumerableRoleAdminChanged) + if err := _AccessControlEnumerable.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil } -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_Admin *AdminCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { - return _Admin.Contract.GetRoleAdmin(&_Admin.CallOpts, role) -} +// AccessControlEnumerableRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the AccessControlEnumerable contract. +type AccessControlEnumerableRoleGrantedIterator struct { + Event *AccessControlEnumerableRoleGranted // Event containing the contract specifics and raw log -// HasRole is a free data retrieval call binding the contract method 0x91d14854. -// -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_Admin *AdminCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "hasRole", role, account) + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data - if err != nil { - return *new(bool), err + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AccessControlEnumerableRoleGrantedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(AccessControlEnumerableRoleGranted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(AccessControlEnumerableRoleGranted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true - return out0, err + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} +// Error returns any retrieval or parsing error occurred during filtering. +func (it *AccessControlEnumerableRoleGrantedIterator) Error() error { + return it.fail } -// HasRole is a free data retrieval call binding the contract method 0x91d14854. -// -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_Admin *AdminSession) HasRole(role [32]byte, account common.Address) (bool, error) { - return _Admin.Contract.HasRole(&_Admin.CallOpts, role, account) +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AccessControlEnumerableRoleGrantedIterator) Close() error { + it.sub.Unsubscribe() + return nil } -// HasRole is a free data retrieval call binding the contract method 0x91d14854. -// -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_Admin *AdminCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { - return _Admin.Contract.HasRole(&_Admin.CallOpts, role, account) +// AccessControlEnumerableRoleGranted represents a RoleGranted event raised by the AccessControlEnumerable contract. +type AccessControlEnumerableRoleGranted struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos } -// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. // -// Solidity: function protocolFeeRate() view returns(uint256) -func (_Admin *AdminCaller) ProtocolFeeRate(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "protocolFeeRate") +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_AccessControlEnumerable *AccessControlEnumerableFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*AccessControlEnumerableRoleGrantedIterator, error) { - if err != nil { - return *new(*big.Int), err + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) } - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. -// -// Solidity: function protocolFeeRate() view returns(uint256) -func (_Admin *AdminSession) ProtocolFeeRate() (*big.Int, error) { - return _Admin.Contract.ProtocolFeeRate(&_Admin.CallOpts) + logs, sub, err := _AccessControlEnumerable.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return &AccessControlEnumerableRoleGrantedIterator{contract: _AccessControlEnumerable.contract, event: "RoleGranted", logs: logs, sub: sub}, nil } -// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. // -// Solidity: function protocolFeeRate() view returns(uint256) -func (_Admin *AdminCallerSession) ProtocolFeeRate() (*big.Int, error) { - return _Admin.Contract.ProtocolFeeRate(&_Admin.CallOpts) -} +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_AccessControlEnumerable *AccessControlEnumerableFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *AccessControlEnumerableRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { -// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. -// -// Solidity: function protocolFees(address ) view returns(uint256) -func (_Admin *AdminCaller) ProtocolFees(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "protocolFees", arg0) + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + logs, sub, err := _AccessControlEnumerable.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) if err != nil { - return *new(*big.Int), err + return nil, err } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(AccessControlEnumerableRoleGranted) + if err := _AccessControlEnumerable.contract.UnpackLog(event, "RoleGranted", log); err != nil { + return err + } + event.Raw = log - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil } -// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. -// -// Solidity: function protocolFees(address ) view returns(uint256) -func (_Admin *AdminSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { - return _Admin.Contract.ProtocolFees(&_Admin.CallOpts, arg0) -} - -// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. -// -// Solidity: function protocolFees(address ) view returns(uint256) -func (_Admin *AdminCallerSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { - return _Admin.Contract.ProtocolFees(&_Admin.CallOpts, arg0) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. // -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_Admin *AdminCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { - var out []interface{} - err := _Admin.contract.Call(opts, &out, "supportsInterface", interfaceId) - - if err != nil { - return *new(bool), err +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_AccessControlEnumerable *AccessControlEnumerableFilterer) ParseRoleGranted(log types.Log) (*AccessControlEnumerableRoleGranted, error) { + event := new(AccessControlEnumerableRoleGranted) + if err := _AccessControlEnumerable.contract.UnpackLog(event, "RoleGranted", log); err != nil { + return nil, err } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_Admin *AdminSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _Admin.Contract.SupportsInterface(&_Admin.CallOpts, interfaceId) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_Admin *AdminCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _Admin.Contract.SupportsInterface(&_Admin.CallOpts, interfaceId) -} - -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. -// -// Solidity: function addGovernor(address _governor) returns() -func (_Admin *AdminTransactor) AddGovernor(opts *bind.TransactOpts, _governor common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "addGovernor", _governor) -} - -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. -// -// Solidity: function addGovernor(address _governor) returns() -func (_Admin *AdminSession) AddGovernor(_governor common.Address) (*types.Transaction, error) { - return _Admin.Contract.AddGovernor(&_Admin.TransactOpts, _governor) -} - -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. -// -// Solidity: function addGovernor(address _governor) returns() -func (_Admin *AdminTransactorSession) AddGovernor(_governor common.Address) (*types.Transaction, error) { - return _Admin.Contract.AddGovernor(&_Admin.TransactOpts, _governor) -} - -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. -// -// Solidity: function addGuard(address _guard) returns() -func (_Admin *AdminTransactor) AddGuard(opts *bind.TransactOpts, _guard common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "addGuard", _guard) -} - -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. -// -// Solidity: function addGuard(address _guard) returns() -func (_Admin *AdminSession) AddGuard(_guard common.Address) (*types.Transaction, error) { - return _Admin.Contract.AddGuard(&_Admin.TransactOpts, _guard) -} - -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. -// -// Solidity: function addGuard(address _guard) returns() -func (_Admin *AdminTransactorSession) AddGuard(_guard common.Address) (*types.Transaction, error) { - return _Admin.Contract.AddGuard(&_Admin.TransactOpts, _guard) -} - -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. -// -// Solidity: function addRelayer(address _relayer) returns() -func (_Admin *AdminTransactor) AddRelayer(opts *bind.TransactOpts, _relayer common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "addRelayer", _relayer) -} - -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. -// -// Solidity: function addRelayer(address _relayer) returns() -func (_Admin *AdminSession) AddRelayer(_relayer common.Address) (*types.Transaction, error) { - return _Admin.Contract.AddRelayer(&_Admin.TransactOpts, _relayer) -} - -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. -// -// Solidity: function addRelayer(address _relayer) returns() -func (_Admin *AdminTransactorSession) AddRelayer(_relayer common.Address) (*types.Transaction, error) { - return _Admin.Contract.AddRelayer(&_Admin.TransactOpts, _relayer) -} - -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. -// -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_Admin *AdminTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "grantRole", role, account) -} - -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. -// -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_Admin *AdminSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _Admin.Contract.GrantRole(&_Admin.TransactOpts, role, account) -} - -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. -// -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_Admin *AdminTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _Admin.Contract.GrantRole(&_Admin.TransactOpts, role, account) -} - -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. -// -// Solidity: function removeGovernor(address _governor) returns() -func (_Admin *AdminTransactor) RemoveGovernor(opts *bind.TransactOpts, _governor common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "removeGovernor", _governor) -} - -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. -// -// Solidity: function removeGovernor(address _governor) returns() -func (_Admin *AdminSession) RemoveGovernor(_governor common.Address) (*types.Transaction, error) { - return _Admin.Contract.RemoveGovernor(&_Admin.TransactOpts, _governor) -} - -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. -// -// Solidity: function removeGovernor(address _governor) returns() -func (_Admin *AdminTransactorSession) RemoveGovernor(_governor common.Address) (*types.Transaction, error) { - return _Admin.Contract.RemoveGovernor(&_Admin.TransactOpts, _governor) -} - -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. -// -// Solidity: function removeGuard(address _guard) returns() -func (_Admin *AdminTransactor) RemoveGuard(opts *bind.TransactOpts, _guard common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "removeGuard", _guard) -} - -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. -// -// Solidity: function removeGuard(address _guard) returns() -func (_Admin *AdminSession) RemoveGuard(_guard common.Address) (*types.Transaction, error) { - return _Admin.Contract.RemoveGuard(&_Admin.TransactOpts, _guard) -} - -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. -// -// Solidity: function removeGuard(address _guard) returns() -func (_Admin *AdminTransactorSession) RemoveGuard(_guard common.Address) (*types.Transaction, error) { - return _Admin.Contract.RemoveGuard(&_Admin.TransactOpts, _guard) -} - -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. -// -// Solidity: function removeRelayer(address _relayer) returns() -func (_Admin *AdminTransactor) RemoveRelayer(opts *bind.TransactOpts, _relayer common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "removeRelayer", _relayer) -} - -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. -// -// Solidity: function removeRelayer(address _relayer) returns() -func (_Admin *AdminSession) RemoveRelayer(_relayer common.Address) (*types.Transaction, error) { - return _Admin.Contract.RemoveRelayer(&_Admin.TransactOpts, _relayer) -} - -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. -// -// Solidity: function removeRelayer(address _relayer) returns() -func (_Admin *AdminTransactorSession) RemoveRelayer(_relayer common.Address) (*types.Transaction, error) { - return _Admin.Contract.RemoveRelayer(&_Admin.TransactOpts, _relayer) -} - -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. -// -// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() -func (_Admin *AdminTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "renounceRole", role, callerConfirmation) -} - -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. -// -// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() -func (_Admin *AdminSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { - return _Admin.Contract.RenounceRole(&_Admin.TransactOpts, role, callerConfirmation) -} - -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. -// -// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() -func (_Admin *AdminTransactorSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { - return _Admin.Contract.RenounceRole(&_Admin.TransactOpts, role, callerConfirmation) -} - -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. -// -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_Admin *AdminTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "revokeRole", role, account) -} - -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. -// -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_Admin *AdminSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _Admin.Contract.RevokeRole(&_Admin.TransactOpts, role, account) -} - -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. -// -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_Admin *AdminTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _Admin.Contract.RevokeRole(&_Admin.TransactOpts, role, account) -} - -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. -// -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_Admin *AdminTransactor) SetChainGasAmount(opts *bind.TransactOpts, newChainGasAmount *big.Int) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "setChainGasAmount", newChainGasAmount) -} - -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. -// -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_Admin *AdminSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { - return _Admin.Contract.SetChainGasAmount(&_Admin.TransactOpts, newChainGasAmount) -} - -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. -// -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_Admin *AdminTransactorSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { - return _Admin.Contract.SetChainGasAmount(&_Admin.TransactOpts, newChainGasAmount) -} - -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. -// -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_Admin *AdminTransactor) SetProtocolFeeRate(opts *bind.TransactOpts, newFeeRate *big.Int) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "setProtocolFeeRate", newFeeRate) -} - -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. -// -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_Admin *AdminSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { - return _Admin.Contract.SetProtocolFeeRate(&_Admin.TransactOpts, newFeeRate) -} - -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. -// -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_Admin *AdminTransactorSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { - return _Admin.Contract.SetProtocolFeeRate(&_Admin.TransactOpts, newFeeRate) -} - -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. -// -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_Admin *AdminTransactor) SweepProtocolFees(opts *bind.TransactOpts, token common.Address, recipient common.Address) (*types.Transaction, error) { - return _Admin.contract.Transact(opts, "sweepProtocolFees", token, recipient) -} - -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. -// -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_Admin *AdminSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { - return _Admin.Contract.SweepProtocolFees(&_Admin.TransactOpts, token, recipient) -} - -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. -// -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_Admin *AdminTransactorSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { - return _Admin.Contract.SweepProtocolFees(&_Admin.TransactOpts, token, recipient) + event.Raw = log + return event, nil } -// AdminChainGasAmountUpdatedIterator is returned from FilterChainGasAmountUpdated and is used to iterate over the raw logs and unpacked data for ChainGasAmountUpdated events raised by the Admin contract. -type AdminChainGasAmountUpdatedIterator struct { - Event *AdminChainGasAmountUpdated // Event containing the contract specifics and raw log +// AccessControlEnumerableRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the AccessControlEnumerable contract. +type AccessControlEnumerableRoleRevokedIterator struct { + Event *AccessControlEnumerableRoleRevoked // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -1911,7 +1650,7 @@ type AdminChainGasAmountUpdatedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *AdminChainGasAmountUpdatedIterator) Next() bool { +func (it *AccessControlEnumerableRoleRevokedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -1920,7 +1659,7 @@ func (it *AdminChainGasAmountUpdatedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(AdminChainGasAmountUpdated) + it.Event = new(AccessControlEnumerableRoleRevoked) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1935,7 +1674,7 @@ func (it *AdminChainGasAmountUpdatedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(AdminChainGasAmountUpdated) + it.Event = new(AccessControlEnumerableRoleRevoked) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1951,42 +1690,69 @@ func (it *AdminChainGasAmountUpdatedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminChainGasAmountUpdatedIterator) Error() error { +func (it *AccessControlEnumerableRoleRevokedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *AdminChainGasAmountUpdatedIterator) Close() error { +func (it *AccessControlEnumerableRoleRevokedIterator) Close() error { it.sub.Unsubscribe() return nil } -// AdminChainGasAmountUpdated represents a ChainGasAmountUpdated event raised by the Admin contract. -type AdminChainGasAmountUpdated struct { - OldChainGasAmount *big.Int - NewChainGasAmount *big.Int - Raw types.Log // Blockchain specific contextual infos +// AccessControlEnumerableRoleRevoked represents a RoleRevoked event raised by the AccessControlEnumerable contract. +type AccessControlEnumerableRoleRevoked struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos } -// FilterChainGasAmountUpdated is a free log retrieval operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. +// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_Admin *AdminFilterer) FilterChainGasAmountUpdated(opts *bind.FilterOpts) (*AdminChainGasAmountUpdatedIterator, error) { +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_AccessControlEnumerable *AccessControlEnumerableFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*AccessControlEnumerableRoleRevokedIterator, error) { - logs, sub, err := _Admin.contract.FilterLogs(opts, "ChainGasAmountUpdated") - if err != nil { - return nil, err + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) } - return &AdminChainGasAmountUpdatedIterator{contract: _Admin.contract, event: "ChainGasAmountUpdated", logs: logs, sub: sub}, nil -} -// WatchChainGasAmountUpdated is a free log subscription operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. + logs, sub, err := _AccessControlEnumerable.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return &AccessControlEnumerableRoleRevokedIterator{contract: _AccessControlEnumerable.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil +} + +// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_Admin *AdminFilterer) WatchChainGasAmountUpdated(opts *bind.WatchOpts, sink chan<- *AdminChainGasAmountUpdated) (event.Subscription, error) { +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_AccessControlEnumerable *AccessControlEnumerableFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *AccessControlEnumerableRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { - logs, sub, err := _Admin.contract.WatchLogs(opts, "ChainGasAmountUpdated") + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _AccessControlEnumerable.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) if err != nil { return nil, err } @@ -1996,8 +1762,8 @@ func (_Admin *AdminFilterer) WatchChainGasAmountUpdated(opts *bind.WatchOpts, si select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(AdminChainGasAmountUpdated) - if err := _Admin.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { + event := new(AccessControlEnumerableRoleRevoked) + if err := _AccessControlEnumerable.contract.UnpackLog(event, "RoleRevoked", log); err != nil { return err } event.Raw = log @@ -2018,1420 +1784,985 @@ func (_Admin *AdminFilterer) WatchChainGasAmountUpdated(opts *bind.WatchOpts, si }), nil } -// ParseChainGasAmountUpdated is a log parse operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. +// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_Admin *AdminFilterer) ParseChainGasAmountUpdated(log types.Log) (*AdminChainGasAmountUpdated, error) { - event := new(AdminChainGasAmountUpdated) - if err := _Admin.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_AccessControlEnumerable *AccessControlEnumerableFilterer) ParseRoleRevoked(log types.Log) (*AccessControlEnumerableRoleRevoked, error) { + event := new(AccessControlEnumerableRoleRevoked) + if err := _AccessControlEnumerable.contract.UnpackLog(event, "RoleRevoked", log); err != nil { return nil, err } event.Raw = log return event, nil } -// AdminFeeRateUpdatedIterator is returned from FilterFeeRateUpdated and is used to iterate over the raw logs and unpacked data for FeeRateUpdated events raised by the Admin contract. -type AdminFeeRateUpdatedIterator struct { - Event *AdminFeeRateUpdated // Event containing the contract specifics and raw log +// AddressMetaData contains all meta data concerning the Address contract. +var AddressMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"}]", + Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122069309b4b154b9a5a3f92efe9269fb006052caf08cd8c5c5c6db55daf70b3227964736f6c63430008140033", +} - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data +// AddressABI is the input ABI used to generate the binding from. +// Deprecated: Use AddressMetaData.ABI instead. +var AddressABI = AddressMetaData.ABI - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} +// AddressBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use AddressMetaData.Bin instead. +var AddressBin = AddressMetaData.Bin -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminFeeRateUpdatedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false +// DeployAddress deploys a new Ethereum contract, binding an instance of Address to it. +func DeployAddress(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Address, error) { + parsed, err := AddressMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminFeeRateUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminFeeRateUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(AddressBin), backend) + if err != nil { + return common.Address{}, nil, nil, err } + return address, tx, &Address{AddressCaller: AddressCaller{contract: contract}, AddressTransactor: AddressTransactor{contract: contract}, AddressFilterer: AddressFilterer{contract: contract}}, nil } -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminFeeRateUpdatedIterator) Error() error { - return it.fail +// Address is an auto generated Go binding around an Ethereum contract. +type Address struct { + AddressCaller // Read-only binding to the contract + AddressTransactor // Write-only binding to the contract + AddressFilterer // Log filterer for contract events } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminFeeRateUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// AddressCaller is an auto generated read-only Go binding around an Ethereum contract. +type AddressCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// AdminFeeRateUpdated represents a FeeRateUpdated event raised by the Admin contract. -type AdminFeeRateUpdated struct { - OldFeeRate *big.Int - NewFeeRate *big.Int - Raw types.Log // Blockchain specific contextual infos +// AddressTransactor is an auto generated write-only Go binding around an Ethereum contract. +type AddressTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// FilterFeeRateUpdated is a free log retrieval operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. -// -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_Admin *AdminFilterer) FilterFeeRateUpdated(opts *bind.FilterOpts) (*AdminFeeRateUpdatedIterator, error) { +// AddressFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type AddressFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} - logs, sub, err := _Admin.contract.FilterLogs(opts, "FeeRateUpdated") +// AddressSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type AddressSession struct { + Contract *Address // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// AddressCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type AddressCallerSession struct { + Contract *AddressCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// AddressTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type AddressTransactorSession struct { + Contract *AddressTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// AddressRaw is an auto generated low-level Go binding around an Ethereum contract. +type AddressRaw struct { + Contract *Address // Generic contract binding to access the raw methods on +} + +// AddressCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type AddressCallerRaw struct { + Contract *AddressCaller // Generic read-only contract binding to access the raw methods on +} + +// AddressTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type AddressTransactorRaw struct { + Contract *AddressTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewAddress creates a new instance of Address, bound to a specific deployed contract. +func NewAddress(address common.Address, backend bind.ContractBackend) (*Address, error) { + contract, err := bindAddress(address, backend, backend, backend) if err != nil { return nil, err } - return &AdminFeeRateUpdatedIterator{contract: _Admin.contract, event: "FeeRateUpdated", logs: logs, sub: sub}, nil + return &Address{AddressCaller: AddressCaller{contract: contract}, AddressTransactor: AddressTransactor{contract: contract}, AddressFilterer: AddressFilterer{contract: contract}}, nil } -// WatchFeeRateUpdated is a free log subscription operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. -// -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_Admin *AdminFilterer) WatchFeeRateUpdated(opts *bind.WatchOpts, sink chan<- *AdminFeeRateUpdated) (event.Subscription, error) { +// NewAddressCaller creates a new read-only instance of Address, bound to a specific deployed contract. +func NewAddressCaller(address common.Address, caller bind.ContractCaller) (*AddressCaller, error) { + contract, err := bindAddress(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &AddressCaller{contract: contract}, nil +} - logs, sub, err := _Admin.contract.WatchLogs(opts, "FeeRateUpdated") +// NewAddressTransactor creates a new write-only instance of Address, bound to a specific deployed contract. +func NewAddressTransactor(address common.Address, transactor bind.ContractTransactor) (*AddressTransactor, error) { + contract, err := bindAddress(address, nil, transactor, nil) if err != nil { return nil, err } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminFeeRateUpdated) - if err := _Admin.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { - return err - } - event.Raw = log + return &AddressTransactor{contract: contract}, nil +} - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil +// NewAddressFilterer creates a new log filterer instance of Address, bound to a specific deployed contract. +func NewAddressFilterer(address common.Address, filterer bind.ContractFilterer) (*AddressFilterer, error) { + contract, err := bindAddress(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &AddressFilterer{contract: contract}, nil } -// ParseFeeRateUpdated is a log parse operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. -// -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_Admin *AdminFilterer) ParseFeeRateUpdated(log types.Log) (*AdminFeeRateUpdated, error) { - event := new(AdminFeeRateUpdated) - if err := _Admin.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { +// bindAddress binds a generic wrapper to an already deployed contract. +func bindAddress(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := AddressMetaData.GetAbi() + if err != nil { return nil, err } - event.Raw = log - return event, nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } -// AdminFeesSweptIterator is returned from FilterFeesSwept and is used to iterate over the raw logs and unpacked data for FeesSwept events raised by the Admin contract. -type AdminFeesSweptIterator struct { - Event *AdminFeesSwept // Event containing the contract specifics and raw log +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Address *AddressRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Address.Contract.AddressCaller.contract.Call(opts, result, method, params...) +} - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Address *AddressRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Address.Contract.AddressTransactor.contract.Transfer(opts) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminFeesSweptIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminFeesSwept) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminFeesSwept) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// Transact invokes the (paid) contract method with params as input values. +func (_Address *AddressRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Address.Contract.AddressTransactor.contract.Transact(opts, method, params...) +} - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Address *AddressCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Address.Contract.contract.Call(opts, result, method, params...) } -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminFeesSweptIterator) Error() error { - return it.fail +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Address *AddressTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Address.Contract.contract.Transfer(opts) } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminFeesSweptIterator) Close() error { - it.sub.Unsubscribe() - return nil +// Transact invokes the (paid) contract method with params as input values. +func (_Address *AddressTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Address.Contract.contract.Transact(opts, method, params...) } -// AdminFeesSwept represents a FeesSwept event raised by the Admin contract. -type AdminFeesSwept struct { - Token common.Address - Recipient common.Address - Amount *big.Int - Raw types.Log // Blockchain specific contextual infos +// AdminMetaData contains all meta data concerning the Admin contract. +var AdminMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REFUNDER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "a217fddf": "DEFAULT_ADMIN_ROLE()", + "bf333f2c": "FEE_BPS()", + "0f5f6ed7": "FEE_RATE_MAX()", + "ccc57490": "GOVERNOR_ROLE()", + "03ed0ee5": "GUARD_ROLE()", + "5960ccf2": "REFUNDER_ROLE()", + "926d7d7f": "RELAYER_ROLE()", + "e00a83e0": "chainGasAmount()", + "248a9ca3": "getRoleAdmin(bytes32)", + "9010d07c": "getRoleMember(bytes32,uint256)", + "ca15c873": "getRoleMemberCount(bytes32)", + "2f2ff15d": "grantRole(bytes32,address)", + "91d14854": "hasRole(bytes32,address)", + "58f85880": "protocolFeeRate()", + "dcf844a7": "protocolFees(address)", + "36568abe": "renounceRole(bytes32,address)", + "d547741f": "revokeRole(bytes32,address)", + "b250fe6b": "setChainGasAmount(uint256)", + "b13aa2d6": "setProtocolFeeRate(uint256)", + "01ffc9a7": "supportsInterface(bytes4)", + "06f333f2": "sweepProtocolFees(address,address)", + }, + Bin: "0x60806040523480156200001157600080fd5b50604051620014123803806200141283398101604081905262000034916200018e565b6200004160008262000049565b5050620001b9565b60008062000058848462000086565b905080156200007d5760008481526001602052604090206200007b908462000134565b505b90505b92915050565b6000828152602081815260408083206001600160a01b038516845290915281205460ff166200012b576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620000e23390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600162000080565b50600062000080565b60006200007d836001600160a01b03841660008181526001830160205260408120546200012b5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000080565b600060208284031215620001a157600080fd5b81516001600160a01b03811681146200007d57600080fd5b61124980620001c96000396000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806391d14854116100d8578063bf333f2c1161008c578063d547741f11610066578063d547741f14610385578063dcf844a714610398578063e00a83e0146103b857600080fd5b8063bf333f2c14610341578063ca15c8731461034b578063ccc574901461035e57600080fd5b8063a217fddf116100bd578063a217fddf14610313578063b13aa2d61461031b578063b250fe6b1461032e57600080fd5b806391d14854146102a8578063926d7d7f146102ec57600080fd5b80632f2ff15d1161012f57806358f858801161011457806358f85880146102405780635960ccf2146102495780639010d07c1461027057600080fd5b80632f2ff15d1461021a57806336568abe1461022d57600080fd5b806306f333f21161016057806306f333f2146101d95780630f5f6ed7146101ee578063248a9ca3146101f757600080fd5b806301ffc9a71461017c57806303ed0ee5146101a4575b600080fd5b61018f61018a366004611013565b6103c1565b60405190151581526020015b60405180910390f35b6101cb7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b60405190815260200161019b565b6101ec6101e736600461107e565b61041d565b005b6101cb61271081565b6101cb6102053660046110b1565b60009081526020819052604090206001015490565b6101ec6102283660046110ca565b61050b565b6101ec61023b3660046110ca565b610536565b6101cb60025481565b6101cb7fdb9556138406326f00296e13ea2ad7db24ba82381212d816b1a40c23b466b32781565b61028361027e3660046110ed565b61058f565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b61018f6102b63660046110ca565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6101cb7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b6101cb600081565b6101ec6103293660046110b1565b6105ae565b6101ec61033c3660046110b1565b610690565b6101cb620f424081565b6101cb6103593660046110b1565b6106f8565b6101cb7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b6101ec6103933660046110ca565b61070f565b6101cb6103a636600461110f565b60036020526000908152604090205481565b6101cb60045481565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f000000000000000000000000000000000000000000000000000000001480610417575061041782610734565b92915050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55610447816107cb565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120549081900361047b5750505050565b73ffffffffffffffffffffffffffffffffffffffff84166000818152600360205260408120556104ac9084836107d8565b6040805173ffffffffffffffffffffffffffffffffffffffff8087168252851660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b505050565b600082815260208190526040902060010154610526816107cb565b610530838361092f565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610585576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105068282610964565b60008281526001602052604081206105a79083610991565b9392505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556105d8816107cb565b612710821115610649576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064015b60405180910390fd5b600280549083905560408051828152602081018590527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a1505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556106ba816107cb565b600480549083905560408051828152602081018590527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa9101610683565b60008181526001602052604081206104179061099d565b60008281526020819052604090206001015461072a816107cb565b6105308383610964565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061041757507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610417565b6107d581336109a7565b50565b3073ffffffffffffffffffffffffffffffffffffffff8316036107fa57505050565b8060000361080757505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff84160161090e5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461089e576040519150601f19603f3d011682016040523d82523d6000602084013e6108a3565b606091505b5050905080610530576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c6564000000000000000000000000006044820152606401610640565b61050673ffffffffffffffffffffffffffffffffffffffff84168383610a31565b60008061093c8484610abe565b905080156105a757600084815260016020526040902061095c9084610bba565b509392505050565b6000806109718484610bdc565b905080156105a757600084815260016020526040902061095c9084610c97565b60006105a78383610cb9565b6000610417825490565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610a2d576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260248101839052604401610640565b5050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610506908490610ce3565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16610bb25760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610b503390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610417565b506000610417565b60006105a78373ffffffffffffffffffffffffffffffffffffffff8416610d79565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff1615610bb25760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610417565b60006105a78373ffffffffffffffffffffffffffffffffffffffff8416610dc0565b6000826000018281548110610cd057610cd061112a565b9060005260206000200154905092915050565b6000610d0573ffffffffffffffffffffffffffffffffffffffff841683610eb3565b90508051600014158015610d2a575080806020019051810190610d289190611159565b155b15610506576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610640565b6000818152600183016020526040812054610bb257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610417565b60008181526001830160205260408120548015610ea9576000610de460018361117b565b8554909150600090610df89060019061117b565b9050808214610e5d576000866000018281548110610e1857610e1861112a565b9060005260206000200154905080876000018481548110610e3b57610e3b61112a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080610e6e57610e6e6111b5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610417565b6000915050610417565b60606105a783836000846000808573ffffffffffffffffffffffffffffffffffffffff168486604051610ee691906111e4565b60006040518083038185875af1925050503d8060008114610f23576040519150601f19603f3d011682016040523d82523d6000602084013e610f28565b606091505b5091509150610f38868383610f42565b9695505050505050565b606082610f5757610f5282610fd1565b6105a7565b8151158015610f7b575073ffffffffffffffffffffffffffffffffffffffff84163b155b15610fca576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610640565b50806105a7565b805115610fe15780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561102557600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146105a757600080fd5b803573ffffffffffffffffffffffffffffffffffffffff8116811461107957600080fd5b919050565b6000806040838503121561109157600080fd5b61109a83611055565b91506110a860208401611055565b90509250929050565b6000602082840312156110c357600080fd5b5035919050565b600080604083850312156110dd57600080fd5b823591506110a860208401611055565b6000806040838503121561110057600080fd5b50508035926020909101359150565b60006020828403121561112157600080fd5b6105a782611055565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561116b57600080fd5b815180151581146105a757600080fd5b81810381811115610417577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000825160005b8181101561120557602081860181015185830152016111eb565b50600092019182525091905056fea26469706673582212201dd993fc5abfac80cc090826421c56b0e7f52ac1e663c8aeeb7526f35e1246c464736f6c63430008140033", } -// FilterFeesSwept is a free log retrieval operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. -// -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_Admin *AdminFilterer) FilterFeesSwept(opts *bind.FilterOpts) (*AdminFeesSweptIterator, error) { +// AdminABI is the input ABI used to generate the binding from. +// Deprecated: Use AdminMetaData.ABI instead. +var AdminABI = AdminMetaData.ABI - logs, sub, err := _Admin.contract.FilterLogs(opts, "FeesSwept") - if err != nil { - return nil, err - } - return &AdminFeesSweptIterator{contract: _Admin.contract, event: "FeesSwept", logs: logs, sub: sub}, nil -} +// Deprecated: Use AdminMetaData.Sigs instead. +// AdminFuncSigs maps the 4-byte function signature to its string representation. +var AdminFuncSigs = AdminMetaData.Sigs -// WatchFeesSwept is a free log subscription operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. -// -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_Admin *AdminFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink chan<- *AdminFeesSwept) (event.Subscription, error) { +// AdminBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use AdminMetaData.Bin instead. +var AdminBin = AdminMetaData.Bin - logs, sub, err := _Admin.contract.WatchLogs(opts, "FeesSwept") +// DeployAdmin deploys a new Ethereum contract, binding an instance of Admin to it. +func DeployAdmin(auth *bind.TransactOpts, backend bind.ContractBackend, _owner common.Address) (common.Address, *types.Transaction, *Admin, error) { + parsed, err := AdminMetaData.GetAbi() if err != nil { - return nil, err + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminFeesSwept) - if err := _Admin.contract.UnpackLog(event, "FeesSwept", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} -// ParseFeesSwept is a log parse operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. -// -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_Admin *AdminFilterer) ParseFeesSwept(log types.Log) (*AdminFeesSwept, error) { - event := new(AdminFeesSwept) - if err := _Admin.contract.UnpackLog(event, "FeesSwept", log); err != nil { - return nil, err + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(AdminBin), backend, _owner) + if err != nil { + return common.Address{}, nil, nil, err } - event.Raw = log - return event, nil + return address, tx, &Admin{AdminCaller: AdminCaller{contract: contract}, AdminTransactor: AdminTransactor{contract: contract}, AdminFilterer: AdminFilterer{contract: contract}}, nil } -// AdminGovernorAddedIterator is returned from FilterGovernorAdded and is used to iterate over the raw logs and unpacked data for GovernorAdded events raised by the Admin contract. -type AdminGovernorAddedIterator struct { - Event *AdminGovernorAdded // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// Admin is an auto generated Go binding around an Ethereum contract. +type Admin struct { + AdminCaller // Read-only binding to the contract + AdminTransactor // Write-only binding to the contract + AdminFilterer // Log filterer for contract events } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminGovernorAddedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminGovernorAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminGovernorAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } +// AdminCaller is an auto generated read-only Go binding around an Ethereum contract. +type AdminCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminGovernorAddedIterator) Error() error { - return it.fail +// AdminTransactor is an auto generated write-only Go binding around an Ethereum contract. +type AdminTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminGovernorAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// AdminFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type AdminFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// AdminGovernorAdded represents a GovernorAdded event raised by the Admin contract. -type AdminGovernorAdded struct { - Governor common.Address - Raw types.Log // Blockchain specific contextual infos +// AdminSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type AdminSession struct { + Contract *Admin // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// FilterGovernorAdded is a free log retrieval operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. -// -// Solidity: event GovernorAdded(address governor) -func (_Admin *AdminFilterer) FilterGovernorAdded(opts *bind.FilterOpts) (*AdminGovernorAddedIterator, error) { - - logs, sub, err := _Admin.contract.FilterLogs(opts, "GovernorAdded") - if err != nil { - return nil, err - } - return &AdminGovernorAddedIterator{contract: _Admin.contract, event: "GovernorAdded", logs: logs, sub: sub}, nil +// AdminCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type AdminCallerSession struct { + Contract *AdminCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session } -// WatchGovernorAdded is a free log subscription operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. -// -// Solidity: event GovernorAdded(address governor) -func (_Admin *AdminFilterer) WatchGovernorAdded(opts *bind.WatchOpts, sink chan<- *AdminGovernorAdded) (event.Subscription, error) { - - logs, sub, err := _Admin.contract.WatchLogs(opts, "GovernorAdded") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminGovernorAdded) - if err := _Admin.contract.UnpackLog(event, "GovernorAdded", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseGovernorAdded is a log parse operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. -// -// Solidity: event GovernorAdded(address governor) -func (_Admin *AdminFilterer) ParseGovernorAdded(log types.Log) (*AdminGovernorAdded, error) { - event := new(AdminGovernorAdded) - if err := _Admin.contract.UnpackLog(event, "GovernorAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// AdminTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type AdminTransactorSession struct { + Contract *AdminTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// AdminGovernorRemovedIterator is returned from FilterGovernorRemoved and is used to iterate over the raw logs and unpacked data for GovernorRemoved events raised by the Admin contract. -type AdminGovernorRemovedIterator struct { - Event *AdminGovernorRemoved // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// AdminRaw is an auto generated low-level Go binding around an Ethereum contract. +type AdminRaw struct { + Contract *Admin // Generic contract binding to access the raw methods on } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminGovernorRemovedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminGovernorRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminGovernorRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } +// AdminCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type AdminCallerRaw struct { + Contract *AdminCaller // Generic read-only contract binding to access the raw methods on } -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminGovernorRemovedIterator) Error() error { - return it.fail +// AdminTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type AdminTransactorRaw struct { + Contract *AdminTransactor // Generic write-only contract binding to access the raw methods on } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminGovernorRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// NewAdmin creates a new instance of Admin, bound to a specific deployed contract. +func NewAdmin(address common.Address, backend bind.ContractBackend) (*Admin, error) { + contract, err := bindAdmin(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Admin{AdminCaller: AdminCaller{contract: contract}, AdminTransactor: AdminTransactor{contract: contract}, AdminFilterer: AdminFilterer{contract: contract}}, nil } -// AdminGovernorRemoved represents a GovernorRemoved event raised by the Admin contract. -type AdminGovernorRemoved struct { - Governor common.Address - Raw types.Log // Blockchain specific contextual infos +// NewAdminCaller creates a new read-only instance of Admin, bound to a specific deployed contract. +func NewAdminCaller(address common.Address, caller bind.ContractCaller) (*AdminCaller, error) { + contract, err := bindAdmin(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &AdminCaller{contract: contract}, nil } -// FilterGovernorRemoved is a free log retrieval operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. -// -// Solidity: event GovernorRemoved(address governor) -func (_Admin *AdminFilterer) FilterGovernorRemoved(opts *bind.FilterOpts) (*AdminGovernorRemovedIterator, error) { - - logs, sub, err := _Admin.contract.FilterLogs(opts, "GovernorRemoved") +// NewAdminTransactor creates a new write-only instance of Admin, bound to a specific deployed contract. +func NewAdminTransactor(address common.Address, transactor bind.ContractTransactor) (*AdminTransactor, error) { + contract, err := bindAdmin(address, nil, transactor, nil) if err != nil { return nil, err } - return &AdminGovernorRemovedIterator{contract: _Admin.contract, event: "GovernorRemoved", logs: logs, sub: sub}, nil + return &AdminTransactor{contract: contract}, nil } -// WatchGovernorRemoved is a free log subscription operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. -// -// Solidity: event GovernorRemoved(address governor) -func (_Admin *AdminFilterer) WatchGovernorRemoved(opts *bind.WatchOpts, sink chan<- *AdminGovernorRemoved) (event.Subscription, error) { - - logs, sub, err := _Admin.contract.WatchLogs(opts, "GovernorRemoved") +// NewAdminFilterer creates a new log filterer instance of Admin, bound to a specific deployed contract. +func NewAdminFilterer(address common.Address, filterer bind.ContractFilterer) (*AdminFilterer, error) { + contract, err := bindAdmin(address, nil, nil, filterer) if err != nil { return nil, err } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminGovernorRemoved) - if err := _Admin.contract.UnpackLog(event, "GovernorRemoved", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil + return &AdminFilterer{contract: contract}, nil } -// ParseGovernorRemoved is a log parse operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. -// -// Solidity: event GovernorRemoved(address governor) -func (_Admin *AdminFilterer) ParseGovernorRemoved(log types.Log) (*AdminGovernorRemoved, error) { - event := new(AdminGovernorRemoved) - if err := _Admin.contract.UnpackLog(event, "GovernorRemoved", log); err != nil { +// bindAdmin binds a generic wrapper to an already deployed contract. +func bindAdmin(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := AdminMetaData.GetAbi() + if err != nil { return nil, err } - event.Raw = log - return event, nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } -// AdminGuardAddedIterator is returned from FilterGuardAdded and is used to iterate over the raw logs and unpacked data for GuardAdded events raised by the Admin contract. -type AdminGuardAddedIterator struct { - Event *AdminGuardAdded // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Admin *AdminRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Admin.Contract.AdminCaller.contract.Call(opts, result, method, params...) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminGuardAddedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminGuardAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminGuardAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Admin *AdminRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Admin.Contract.AdminTransactor.contract.Transfer(opts) +} - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } +// Transact invokes the (paid) contract method with params as input values. +func (_Admin *AdminRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Admin.Contract.AdminTransactor.contract.Transact(opts, method, params...) } -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminGuardAddedIterator) Error() error { - return it.fail +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Admin *AdminCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Admin.Contract.contract.Call(opts, result, method, params...) } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminGuardAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Admin *AdminTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Admin.Contract.contract.Transfer(opts) } -// AdminGuardAdded represents a GuardAdded event raised by the Admin contract. -type AdminGuardAdded struct { - Guard common.Address - Raw types.Log // Blockchain specific contextual infos +// Transact invokes the (paid) contract method with params as input values. +func (_Admin *AdminTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Admin.Contract.contract.Transact(opts, method, params...) } -// FilterGuardAdded is a free log retrieval operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. // -// Solidity: event GuardAdded(address guard) -func (_Admin *AdminFilterer) FilterGuardAdded(opts *bind.FilterOpts) (*AdminGuardAddedIterator, error) { +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_Admin *AdminCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") - logs, sub, err := _Admin.contract.FilterLogs(opts, "GuardAdded") if err != nil { - return nil, err + return *new([32]byte), err } - return &AdminGuardAddedIterator{contract: _Admin.contract, event: "GuardAdded", logs: logs, sub: sub}, nil + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -// WatchGuardAdded is a free log subscription operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. // -// Solidity: event GuardAdded(address guard) -func (_Admin *AdminFilterer) WatchGuardAdded(opts *bind.WatchOpts, sink chan<- *AdminGuardAdded) (event.Subscription, error) { +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_Admin *AdminSession) DEFAULTADMINROLE() ([32]byte, error) { + return _Admin.Contract.DEFAULTADMINROLE(&_Admin.CallOpts) +} - logs, sub, err := _Admin.contract.WatchLogs(opts, "GuardAdded") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminGuardAdded) - if err := _Admin.contract.UnpackLog(event, "GuardAdded", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_Admin *AdminCallerSession) DEFAULTADMINROLE() ([32]byte, error) { + return _Admin.Contract.DEFAULTADMINROLE(&_Admin.CallOpts) } -// ParseGuardAdded is a log parse operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. // -// Solidity: event GuardAdded(address guard) -func (_Admin *AdminFilterer) ParseGuardAdded(log types.Log) (*AdminGuardAdded, error) { - event := new(AdminGuardAdded) - if err := _Admin.contract.UnpackLog(event, "GuardAdded", log); err != nil { - return nil, err +// Solidity: function FEE_BPS() view returns(uint256) +func (_Admin *AdminCaller) FEEBPS(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "FEE_BPS") + + if err != nil { + return *new(*big.Int), err } - event.Raw = log - return event, nil -} -// AdminGuardRemovedIterator is returned from FilterGuardRemoved and is used to iterate over the raw logs and unpacked data for GuardRemoved events raised by the Admin contract. -type AdminGuardRemovedIterator struct { - Event *AdminGuardRemoved // Event containing the contract specifics and raw log + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data + return out0, err - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminGuardRemovedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminGuardRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. +// +// Solidity: function FEE_BPS() view returns(uint256) +func (_Admin *AdminSession) FEEBPS() (*big.Int, error) { + return _Admin.Contract.FEEBPS(&_Admin.CallOpts) +} - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminGuardRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. +// +// Solidity: function FEE_BPS() view returns(uint256) +func (_Admin *AdminCallerSession) FEEBPS() (*big.Int, error) { + return _Admin.Contract.FEEBPS(&_Admin.CallOpts) +} - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() +// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. +// +// Solidity: function FEE_RATE_MAX() view returns(uint256) +func (_Admin *AdminCaller) FEERATEMAX(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "FEE_RATE_MAX") + + if err != nil { + return *new(*big.Int), err } -} -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminGuardRemovedIterator) Error() error { - return it.fail -} + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminGuardRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} + return out0, err -// AdminGuardRemoved represents a GuardRemoved event raised by the Admin contract. -type AdminGuardRemoved struct { - Guard common.Address - Raw types.Log // Blockchain specific contextual infos } -// FilterGuardRemoved is a free log retrieval operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. // -// Solidity: event GuardRemoved(address guard) -func (_Admin *AdminFilterer) FilterGuardRemoved(opts *bind.FilterOpts) (*AdminGuardRemovedIterator, error) { +// Solidity: function FEE_RATE_MAX() view returns(uint256) +func (_Admin *AdminSession) FEERATEMAX() (*big.Int, error) { + return _Admin.Contract.FEERATEMAX(&_Admin.CallOpts) +} - logs, sub, err := _Admin.contract.FilterLogs(opts, "GuardRemoved") - if err != nil { - return nil, err - } - return &AdminGuardRemovedIterator{contract: _Admin.contract, event: "GuardRemoved", logs: logs, sub: sub}, nil +// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. +// +// Solidity: function FEE_RATE_MAX() view returns(uint256) +func (_Admin *AdminCallerSession) FEERATEMAX() (*big.Int, error) { + return _Admin.Contract.FEERATEMAX(&_Admin.CallOpts) } -// WatchGuardRemoved is a free log subscription operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. // -// Solidity: event GuardRemoved(address guard) -func (_Admin *AdminFilterer) WatchGuardRemoved(opts *bind.WatchOpts, sink chan<- *AdminGuardRemoved) (event.Subscription, error) { +// Solidity: function GOVERNOR_ROLE() view returns(bytes32) +func (_Admin *AdminCaller) GOVERNORROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "GOVERNOR_ROLE") - logs, sub, err := _Admin.contract.WatchLogs(opts, "GuardRemoved") if err != nil { - return nil, err + return *new([32]byte), err } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminGuardRemoved) - if err := _Admin.contract.UnpackLog(event, "GuardRemoved", log); err != nil { - return err - } - event.Raw = log - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -// ParseGuardRemoved is a log parse operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. // -// Solidity: event GuardRemoved(address guard) -func (_Admin *AdminFilterer) ParseGuardRemoved(log types.Log) (*AdminGuardRemoved, error) { - event := new(AdminGuardRemoved) - if err := _Admin.contract.UnpackLog(event, "GuardRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function GOVERNOR_ROLE() view returns(bytes32) +func (_Admin *AdminSession) GOVERNORROLE() ([32]byte, error) { + return _Admin.Contract.GOVERNORROLE(&_Admin.CallOpts) } -// AdminRelayerAddedIterator is returned from FilterRelayerAdded and is used to iterate over the raw logs and unpacked data for RelayerAdded events raised by the Admin contract. -type AdminRelayerAddedIterator struct { - Event *AdminRelayerAdded // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. +// +// Solidity: function GOVERNOR_ROLE() view returns(bytes32) +func (_Admin *AdminCallerSession) GOVERNORROLE() ([32]byte, error) { + return _Admin.Contract.GOVERNORROLE(&_Admin.CallOpts) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminRelayerAddedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminRelayerAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. +// +// Solidity: function GUARD_ROLE() view returns(bytes32) +func (_Admin *AdminCaller) GUARDROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "GUARD_ROLE") - default: - return false - } + if err != nil { + return *new([32]byte), err } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminRelayerAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminRelayerAddedIterator) Error() error { - return it.fail } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminRelayerAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. +// +// Solidity: function GUARD_ROLE() view returns(bytes32) +func (_Admin *AdminSession) GUARDROLE() ([32]byte, error) { + return _Admin.Contract.GUARDROLE(&_Admin.CallOpts) } -// AdminRelayerAdded represents a RelayerAdded event raised by the Admin contract. -type AdminRelayerAdded struct { - Relayer common.Address - Raw types.Log // Blockchain specific contextual infos +// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. +// +// Solidity: function GUARD_ROLE() view returns(bytes32) +func (_Admin *AdminCallerSession) GUARDROLE() ([32]byte, error) { + return _Admin.Contract.GUARDROLE(&_Admin.CallOpts) } -// FilterRelayerAdded is a free log retrieval operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// REFUNDERROLE is a free data retrieval call binding the contract method 0x5960ccf2. // -// Solidity: event RelayerAdded(address relayer) -func (_Admin *AdminFilterer) FilterRelayerAdded(opts *bind.FilterOpts) (*AdminRelayerAddedIterator, error) { +// Solidity: function REFUNDER_ROLE() view returns(bytes32) +func (_Admin *AdminCaller) REFUNDERROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "REFUNDER_ROLE") - logs, sub, err := _Admin.contract.FilterLogs(opts, "RelayerAdded") if err != nil { - return nil, err + return *new([32]byte), err } - return &AdminRelayerAddedIterator{contract: _Admin.contract, event: "RelayerAdded", logs: logs, sub: sub}, nil + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -// WatchRelayerAdded is a free log subscription operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// REFUNDERROLE is a free data retrieval call binding the contract method 0x5960ccf2. // -// Solidity: event RelayerAdded(address relayer) -func (_Admin *AdminFilterer) WatchRelayerAdded(opts *bind.WatchOpts, sink chan<- *AdminRelayerAdded) (event.Subscription, error) { +// Solidity: function REFUNDER_ROLE() view returns(bytes32) +func (_Admin *AdminSession) REFUNDERROLE() ([32]byte, error) { + return _Admin.Contract.REFUNDERROLE(&_Admin.CallOpts) +} + +// REFUNDERROLE is a free data retrieval call binding the contract method 0x5960ccf2. +// +// Solidity: function REFUNDER_ROLE() view returns(bytes32) +func (_Admin *AdminCallerSession) REFUNDERROLE() ([32]byte, error) { + return _Admin.Contract.REFUNDERROLE(&_Admin.CallOpts) +} + +// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. +// +// Solidity: function RELAYER_ROLE() view returns(bytes32) +func (_Admin *AdminCaller) RELAYERROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "RELAYER_ROLE") - logs, sub, err := _Admin.contract.WatchLogs(opts, "RelayerAdded") if err != nil { - return nil, err + return *new([32]byte), err } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminRelayerAdded) - if err := _Admin.contract.UnpackLog(event, "RelayerAdded", log); err != nil { - return err - } - event.Raw = log - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -// ParseRelayerAdded is a log parse operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. // -// Solidity: event RelayerAdded(address relayer) -func (_Admin *AdminFilterer) ParseRelayerAdded(log types.Log) (*AdminRelayerAdded, error) { - event := new(AdminRelayerAdded) - if err := _Admin.contract.UnpackLog(event, "RelayerAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function RELAYER_ROLE() view returns(bytes32) +func (_Admin *AdminSession) RELAYERROLE() ([32]byte, error) { + return _Admin.Contract.RELAYERROLE(&_Admin.CallOpts) } -// AdminRelayerRemovedIterator is returned from FilterRelayerRemoved and is used to iterate over the raw logs and unpacked data for RelayerRemoved events raised by the Admin contract. -type AdminRelayerRemovedIterator struct { - Event *AdminRelayerRemoved // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. +// +// Solidity: function RELAYER_ROLE() view returns(bytes32) +func (_Admin *AdminCallerSession) RELAYERROLE() ([32]byte, error) { + return _Admin.Contract.RELAYERROLE(&_Admin.CallOpts) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminRelayerRemovedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminRelayerRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. +// +// Solidity: function chainGasAmount() view returns(uint256) +func (_Admin *AdminCaller) ChainGasAmount(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "chainGasAmount") - default: - return false - } + if err != nil { + return *new(*big.Int), err } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminRelayerRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminRelayerRemovedIterator) Error() error { - return it.fail } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminRelayerRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. +// +// Solidity: function chainGasAmount() view returns(uint256) +func (_Admin *AdminSession) ChainGasAmount() (*big.Int, error) { + return _Admin.Contract.ChainGasAmount(&_Admin.CallOpts) } -// AdminRelayerRemoved represents a RelayerRemoved event raised by the Admin contract. -type AdminRelayerRemoved struct { - Relayer common.Address - Raw types.Log // Blockchain specific contextual infos +// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. +// +// Solidity: function chainGasAmount() view returns(uint256) +func (_Admin *AdminCallerSession) ChainGasAmount() (*big.Int, error) { + return _Admin.Contract.ChainGasAmount(&_Admin.CallOpts) } -// FilterRelayerRemoved is a free log retrieval operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. // -// Solidity: event RelayerRemoved(address relayer) -func (_Admin *AdminFilterer) FilterRelayerRemoved(opts *bind.FilterOpts) (*AdminRelayerRemovedIterator, error) { +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_Admin *AdminCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "getRoleAdmin", role) - logs, sub, err := _Admin.contract.FilterLogs(opts, "RelayerRemoved") if err != nil { - return nil, err + return *new([32]byte), err } - return &AdminRelayerRemovedIterator{contract: _Admin.contract, event: "RelayerRemoved", logs: logs, sub: sub}, nil + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_Admin *AdminSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _Admin.Contract.GetRoleAdmin(&_Admin.CallOpts, role) +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_Admin *AdminCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _Admin.Contract.GetRoleAdmin(&_Admin.CallOpts, role) } -// WatchRelayerRemoved is a free log subscription operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. // -// Solidity: event RelayerRemoved(address relayer) -func (_Admin *AdminFilterer) WatchRelayerRemoved(opts *bind.WatchOpts, sink chan<- *AdminRelayerRemoved) (event.Subscription, error) { +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_Admin *AdminCaller) GetRoleMember(opts *bind.CallOpts, role [32]byte, index *big.Int) (common.Address, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "getRoleMember", role, index) - logs, sub, err := _Admin.contract.WatchLogs(opts, "RelayerRemoved") if err != nil { - return nil, err + return *new(common.Address), err } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminRelayerRemoved) - if err := _Admin.contract.UnpackLog(event, "RelayerRemoved", log); err != nil { - return err - } - event.Raw = log - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + } -// ParseRelayerRemoved is a log parse operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. // -// Solidity: event RelayerRemoved(address relayer) -func (_Admin *AdminFilterer) ParseRelayerRemoved(log types.Log) (*AdminRelayerRemoved, error) { - event := new(AdminRelayerRemoved) - if err := _Admin.contract.UnpackLog(event, "RelayerRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_Admin *AdminSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _Admin.Contract.GetRoleMember(&_Admin.CallOpts, role, index) } -// AdminRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the Admin contract. -type AdminRoleAdminChangedIterator struct { - Event *AdminRoleAdminChanged // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. +// +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_Admin *AdminCallerSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _Admin.Contract.GetRoleMember(&_Admin.CallOpts, role, index) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminRoleAdminChangedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminRoleAdminChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. +// +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_Admin *AdminCaller) GetRoleMemberCount(opts *bind.CallOpts, role [32]byte) (*big.Int, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "getRoleMemberCount", role) - default: - return false - } + if err != nil { + return *new(*big.Int), err } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminRoleAdminChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminRoleAdminChangedIterator) Error() error { - return it.fail -} + return out0, err -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminRoleAdminChangedIterator) Close() error { - it.sub.Unsubscribe() - return nil } -// AdminRoleAdminChanged represents a RoleAdminChanged event raised by the Admin contract. -type AdminRoleAdminChanged struct { - Role [32]byte - PreviousAdminRole [32]byte - NewAdminRole [32]byte - Raw types.Log // Blockchain specific contextual infos +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. +// +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_Admin *AdminSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _Admin.Contract.GetRoleMemberCount(&_Admin.CallOpts, role) } -// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. // -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_Admin *AdminFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*AdminRoleAdminChangedIterator, error) { +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_Admin *AdminCallerSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _Admin.Contract.GetRoleMemberCount(&_Admin.CallOpts, role) +} - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var previousAdminRoleRule []interface{} - for _, previousAdminRoleItem := range previousAdminRole { - previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) - } - var newAdminRoleRule []interface{} - for _, newAdminRoleItem := range newAdminRole { - newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) - } +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_Admin *AdminCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "hasRole", role, account) - logs, sub, err := _Admin.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { - return nil, err + return *new(bool), err } - return &AdminRoleAdminChangedIterator{contract: _Admin.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + } -// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// HasRole is a free data retrieval call binding the contract method 0x91d14854. // -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_Admin *AdminFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *AdminRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_Admin *AdminSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _Admin.Contract.HasRole(&_Admin.CallOpts, role, account) +} - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var previousAdminRoleRule []interface{} - for _, previousAdminRoleItem := range previousAdminRole { - previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) - } - var newAdminRoleRule []interface{} - for _, newAdminRoleItem := range newAdminRole { - newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) - } +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_Admin *AdminCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _Admin.Contract.HasRole(&_Admin.CallOpts, role, account) +} + +// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// +// Solidity: function protocolFeeRate() view returns(uint256) +func (_Admin *AdminCaller) ProtocolFeeRate(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "protocolFeeRate") - logs, sub, err := _Admin.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { - return nil, err + return *new(*big.Int), err } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminRoleAdminChanged) - if err := _Admin.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { - return err - } - event.Raw = log - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. // -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_Admin *AdminFilterer) ParseRoleAdminChanged(log types.Log) (*AdminRoleAdminChanged, error) { - event := new(AdminRoleAdminChanged) - if err := _Admin.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function protocolFeeRate() view returns(uint256) +func (_Admin *AdminSession) ProtocolFeeRate() (*big.Int, error) { + return _Admin.Contract.ProtocolFeeRate(&_Admin.CallOpts) } -// AdminRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the Admin contract. -type AdminRoleGrantedIterator struct { - Event *AdminRoleGranted // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// +// Solidity: function protocolFeeRate() view returns(uint256) +func (_Admin *AdminCallerSession) ProtocolFeeRate() (*big.Int, error) { + return _Admin.Contract.ProtocolFeeRate(&_Admin.CallOpts) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *AdminRoleGrantedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(AdminRoleGranted) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. +// +// Solidity: function protocolFees(address ) view returns(uint256) +func (_Admin *AdminCaller) ProtocolFees(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "protocolFees", arg0) - default: - return false - } + if err != nil { + return *new(*big.Int), err } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(AdminRoleGranted) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) -// Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminRoleGrantedIterator) Error() error { - return it.fail -} + return out0, err -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *AdminRoleGrantedIterator) Close() error { - it.sub.Unsubscribe() - return nil } -// AdminRoleGranted represents a RoleGranted event raised by the Admin contract. -type AdminRoleGranted struct { - Role [32]byte - Account common.Address - Sender common.Address - Raw types.Log // Blockchain specific contextual infos +// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. +// +// Solidity: function protocolFees(address ) view returns(uint256) +func (_Admin *AdminSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { + return _Admin.Contract.ProtocolFees(&_Admin.CallOpts, arg0) } -// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. // -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_Admin *AdminFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*AdminRoleGrantedIterator, error) { +// Solidity: function protocolFees(address ) view returns(uint256) +func (_Admin *AdminCallerSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { + return _Admin.Contract.ProtocolFees(&_Admin.CallOpts, arg0) +} - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Admin *AdminCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _Admin.contract.Call(opts, &out, "supportsInterface", interfaceId) - logs, sub, err := _Admin.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) if err != nil { - return nil, err + return *new(bool), err } - return &AdminRoleGrantedIterator{contract: _Admin.contract, event: "RoleGranted", logs: logs, sub: sub}, nil + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + } -// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_Admin *AdminFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *AdminRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Admin *AdminSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Admin.Contract.SupportsInterface(&_Admin.CallOpts, interfaceId) +} - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_Admin *AdminCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _Admin.Contract.SupportsInterface(&_Admin.CallOpts, interfaceId) +} - logs, sub, err := _Admin.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(AdminRoleGranted) - if err := _Admin.contract.UnpackLog(event, "RoleGranted", log); err != nil { - return err - } - event.Raw = log +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_Admin *AdminTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _Admin.contract.Transact(opts, "grantRole", role, account) +} - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_Admin *AdminSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Admin.Contract.GrantRole(&_Admin.TransactOpts, role, account) } -// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. // -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_Admin *AdminFilterer) ParseRoleGranted(log types.Log) (*AdminRoleGranted, error) { - event := new(AdminRoleGranted) - if err := _Admin.contract.UnpackLog(event, "RoleGranted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_Admin *AdminTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Admin.Contract.GrantRole(&_Admin.TransactOpts, role, account) } -// AdminRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the Admin contract. -type AdminRoleRevokedIterator struct { - Event *AdminRoleRevoked // Event containing the contract specifics and raw log +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_Admin *AdminTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _Admin.contract.Transact(opts, "renounceRole", role, callerConfirmation) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_Admin *AdminSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _Admin.Contract.RenounceRole(&_Admin.TransactOpts, role, callerConfirmation) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_Admin *AdminTransactorSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _Admin.Contract.RenounceRole(&_Admin.TransactOpts, role, callerConfirmation) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_Admin *AdminTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _Admin.contract.Transact(opts, "revokeRole", role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_Admin *AdminSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Admin.Contract.RevokeRole(&_Admin.TransactOpts, role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_Admin *AdminTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _Admin.Contract.RevokeRole(&_Admin.TransactOpts, role, account) +} + +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_Admin *AdminTransactor) SetChainGasAmount(opts *bind.TransactOpts, newChainGasAmount *big.Int) (*types.Transaction, error) { + return _Admin.contract.Transact(opts, "setChainGasAmount", newChainGasAmount) +} + +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_Admin *AdminSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { + return _Admin.Contract.SetChainGasAmount(&_Admin.TransactOpts, newChainGasAmount) +} + +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_Admin *AdminTransactorSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { + return _Admin.Contract.SetChainGasAmount(&_Admin.TransactOpts, newChainGasAmount) +} + +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. +// +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_Admin *AdminTransactor) SetProtocolFeeRate(opts *bind.TransactOpts, newFeeRate *big.Int) (*types.Transaction, error) { + return _Admin.contract.Transact(opts, "setProtocolFeeRate", newFeeRate) +} + +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. +// +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_Admin *AdminSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { + return _Admin.Contract.SetProtocolFeeRate(&_Admin.TransactOpts, newFeeRate) +} + +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. +// +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_Admin *AdminTransactorSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { + return _Admin.Contract.SetProtocolFeeRate(&_Admin.TransactOpts, newFeeRate) +} + +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_Admin *AdminTransactor) SweepProtocolFees(opts *bind.TransactOpts, token common.Address, recipient common.Address) (*types.Transaction, error) { + return _Admin.contract.Transact(opts, "sweepProtocolFees", token, recipient) +} + +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_Admin *AdminSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { + return _Admin.Contract.SweepProtocolFees(&_Admin.TransactOpts, token, recipient) +} + +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_Admin *AdminTransactorSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { + return _Admin.Contract.SweepProtocolFees(&_Admin.TransactOpts, token, recipient) +} + +// AdminChainGasAmountUpdatedIterator is returned from FilterChainGasAmountUpdated and is used to iterate over the raw logs and unpacked data for ChainGasAmountUpdated events raised by the Admin contract. +type AdminChainGasAmountUpdatedIterator struct { + Event *AdminChainGasAmountUpdated // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -3445,7 +2776,7 @@ type AdminRoleRevokedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *AdminRoleRevokedIterator) Next() bool { +func (it *AdminChainGasAmountUpdatedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -3454,7 +2785,7 @@ func (it *AdminRoleRevokedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(AdminRoleRevoked) + it.Event = new(AdminChainGasAmountUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -3469,7 +2800,7 @@ func (it *AdminRoleRevokedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(AdminRoleRevoked) + it.Event = new(AdminChainGasAmountUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -3485,69 +2816,42 @@ func (it *AdminRoleRevokedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *AdminRoleRevokedIterator) Error() error { +func (it *AdminChainGasAmountUpdatedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *AdminRoleRevokedIterator) Close() error { +func (it *AdminChainGasAmountUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -// AdminRoleRevoked represents a RoleRevoked event raised by the Admin contract. -type AdminRoleRevoked struct { - Role [32]byte - Account common.Address - Sender common.Address - Raw types.Log // Blockchain specific contextual infos +// AdminChainGasAmountUpdated represents a ChainGasAmountUpdated event raised by the Admin contract. +type AdminChainGasAmountUpdated struct { + OldChainGasAmount *big.Int + NewChainGasAmount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// FilterChainGasAmountUpdated is a free log retrieval operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_Admin *AdminFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*AdminRoleRevokedIterator, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_Admin *AdminFilterer) FilterChainGasAmountUpdated(opts *bind.FilterOpts) (*AdminChainGasAmountUpdatedIterator, error) { - logs, sub, err := _Admin.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + logs, sub, err := _Admin.contract.FilterLogs(opts, "ChainGasAmountUpdated") if err != nil { return nil, err } - return &AdminRoleRevokedIterator{contract: _Admin.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil + return &AdminChainGasAmountUpdatedIterator{contract: _Admin.contract, event: "ChainGasAmountUpdated", logs: logs, sub: sub}, nil } -// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// WatchChainGasAmountUpdated is a free log subscription operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_Admin *AdminFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *AdminRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_Admin *AdminFilterer) WatchChainGasAmountUpdated(opts *bind.WatchOpts, sink chan<- *AdminChainGasAmountUpdated) (event.Subscription, error) { - logs, sub, err := _Admin.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + logs, sub, err := _Admin.contract.WatchLogs(opts, "ChainGasAmountUpdated") if err != nil { return nil, err } @@ -3557,8 +2861,8 @@ func (_Admin *AdminFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(AdminRoleRevoked) - if err := _Admin.contract.UnpackLog(event, "RoleRevoked", log); err != nil { + event := new(AdminChainGasAmountUpdated) + if err := _Admin.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { return err } event.Raw = log @@ -3579,1155 +2883,1541 @@ func (_Admin *AdminFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- }), nil } -// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// ParseChainGasAmountUpdated is a log parse operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_Admin *AdminFilterer) ParseRoleRevoked(log types.Log) (*AdminRoleRevoked, error) { - event := new(AdminRoleRevoked) - if err := _Admin.contract.UnpackLog(event, "RoleRevoked", log); err != nil { +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_Admin *AdminFilterer) ParseChainGasAmountUpdated(log types.Log) (*AdminChainGasAmountUpdated, error) { + event := new(AdminChainGasAmountUpdated) + if err := _Admin.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -// ContextMetaData contains all meta data concerning the Context contract. -var ContextMetaData = &bind.MetaData{ - ABI: "[]", -} +// AdminFeeRateUpdatedIterator is returned from FilterFeeRateUpdated and is used to iterate over the raw logs and unpacked data for FeeRateUpdated events raised by the Admin contract. +type AdminFeeRateUpdatedIterator struct { + Event *AdminFeeRateUpdated // Event containing the contract specifics and raw log -// ContextABI is the input ABI used to generate the binding from. -// Deprecated: Use ContextMetaData.ABI instead. -var ContextABI = ContextMetaData.ABI + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data -// Context is an auto generated Go binding around an Ethereum contract. -type Context struct { - ContextCaller // Read-only binding to the contract - ContextTransactor // Write-only binding to the contract - ContextFilterer // Log filterer for contract events -} - -// ContextCaller is an auto generated read-only Go binding around an Ethereum contract. -type ContextCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ContextTransactor is an auto generated write-only Go binding around an Ethereum contract. -type ContextTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration } -// ContextFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type ContextFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AdminFeeRateUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(AdminFeeRateUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true -// ContextSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type ContextSession struct { - Contract *Context // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(AdminFeeRateUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true -// ContextCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type ContextCallerSession struct { - Contract *ContextCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } } -// ContextTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type ContextTransactorSession struct { - Contract *ContextTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +// Error returns any retrieval or parsing error occurred during filtering. +func (it *AdminFeeRateUpdatedIterator) Error() error { + return it.fail } -// ContextRaw is an auto generated low-level Go binding around an Ethereum contract. -type ContextRaw struct { - Contract *Context // Generic contract binding to access the raw methods on +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AdminFeeRateUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil } -// ContextCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type ContextCallerRaw struct { - Contract *ContextCaller // Generic read-only contract binding to access the raw methods on +// AdminFeeRateUpdated represents a FeeRateUpdated event raised by the Admin contract. +type AdminFeeRateUpdated struct { + OldFeeRate *big.Int + NewFeeRate *big.Int + Raw types.Log // Blockchain specific contextual infos } -// ContextTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type ContextTransactorRaw struct { - Contract *ContextTransactor // Generic write-only contract binding to access the raw methods on -} +// FilterFeeRateUpdated is a free log retrieval operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_Admin *AdminFilterer) FilterFeeRateUpdated(opts *bind.FilterOpts) (*AdminFeeRateUpdatedIterator, error) { -// NewContext creates a new instance of Context, bound to a specific deployed contract. -func NewContext(address common.Address, backend bind.ContractBackend) (*Context, error) { - contract, err := bindContext(address, backend, backend, backend) + logs, sub, err := _Admin.contract.FilterLogs(opts, "FeeRateUpdated") if err != nil { return nil, err } - return &Context{ContextCaller: ContextCaller{contract: contract}, ContextTransactor: ContextTransactor{contract: contract}, ContextFilterer: ContextFilterer{contract: contract}}, nil + return &AdminFeeRateUpdatedIterator{contract: _Admin.contract, event: "FeeRateUpdated", logs: logs, sub: sub}, nil } -// NewContextCaller creates a new read-only instance of Context, bound to a specific deployed contract. -func NewContextCaller(address common.Address, caller bind.ContractCaller) (*ContextCaller, error) { - contract, err := bindContext(address, caller, nil, nil) +// WatchFeeRateUpdated is a free log subscription operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_Admin *AdminFilterer) WatchFeeRateUpdated(opts *bind.WatchOpts, sink chan<- *AdminFeeRateUpdated) (event.Subscription, error) { + + logs, sub, err := _Admin.contract.WatchLogs(opts, "FeeRateUpdated") if err != nil { return nil, err } - return &ContextCaller{contract: contract}, nil + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(AdminFeeRateUpdated) + if err := _Admin.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil } -// NewContextTransactor creates a new write-only instance of Context, bound to a specific deployed contract. -func NewContextTransactor(address common.Address, transactor bind.ContractTransactor) (*ContextTransactor, error) { - contract, err := bindContext(address, nil, transactor, nil) - if err != nil { +// ParseFeeRateUpdated is a log parse operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_Admin *AdminFilterer) ParseFeeRateUpdated(log types.Log) (*AdminFeeRateUpdated, error) { + event := new(AdminFeeRateUpdated) + if err := _Admin.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { return nil, err } - return &ContextTransactor{contract: contract}, nil + event.Raw = log + return event, nil } -// NewContextFilterer creates a new log filterer instance of Context, bound to a specific deployed contract. -func NewContextFilterer(address common.Address, filterer bind.ContractFilterer) (*ContextFilterer, error) { - contract, err := bindContext(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &ContextFilterer{contract: contract}, nil +// AdminFeesSweptIterator is returned from FilterFeesSwept and is used to iterate over the raw logs and unpacked data for FeesSwept events raised by the Admin contract. +type AdminFeesSweptIterator struct { + Event *AdminFeesSwept // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration } -// bindContext binds a generic wrapper to an already deployed contract. -func bindContext(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := ContextMetaData.GetAbi() - if err != nil { - return nil, err +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AdminFeesSweptIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(AdminFeesSwept) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Context *ContextRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Context.Contract.ContextCaller.contract.Call(opts, result, method, params...) -} + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(AdminFeesSwept) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Context *ContextRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Context.Contract.ContextTransactor.contract.Transfer(opts) + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } } -// Transact invokes the (paid) contract method with params as input values. -func (_Context *ContextRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Context.Contract.ContextTransactor.contract.Transact(opts, method, params...) +// Error returns any retrieval or parsing error occurred during filtering. +func (it *AdminFeesSweptIterator) Error() error { + return it.fail } -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Context *ContextCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Context.Contract.contract.Call(opts, result, method, params...) +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AdminFeesSweptIterator) Close() error { + it.sub.Unsubscribe() + return nil } -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Context *ContextTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Context.Contract.contract.Transfer(opts) +// AdminFeesSwept represents a FeesSwept event raised by the Admin contract. +type AdminFeesSwept struct { + Token common.Address + Recipient common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// Transact invokes the (paid) contract method with params as input values. -func (_Context *ContextTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Context.Contract.contract.Transact(opts, method, params...) -} +// FilterFeesSwept is a free log retrieval operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_Admin *AdminFilterer) FilterFeesSwept(opts *bind.FilterOpts) (*AdminFeesSweptIterator, error) { -// ERC165MetaData contains all meta data concerning the ERC165 contract. -var ERC165MetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Sigs: map[string]string{ - "01ffc9a7": "supportsInterface(bytes4)", - }, + logs, sub, err := _Admin.contract.FilterLogs(opts, "FeesSwept") + if err != nil { + return nil, err + } + return &AdminFeesSweptIterator{contract: _Admin.contract, event: "FeesSwept", logs: logs, sub: sub}, nil } -// ERC165ABI is the input ABI used to generate the binding from. -// Deprecated: Use ERC165MetaData.ABI instead. -var ERC165ABI = ERC165MetaData.ABI +// WatchFeesSwept is a free log subscription operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_Admin *AdminFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink chan<- *AdminFeesSwept) (event.Subscription, error) { -// Deprecated: Use ERC165MetaData.Sigs instead. -// ERC165FuncSigs maps the 4-byte function signature to its string representation. -var ERC165FuncSigs = ERC165MetaData.Sigs + logs, sub, err := _Admin.contract.WatchLogs(opts, "FeesSwept") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(AdminFeesSwept) + if err := _Admin.contract.UnpackLog(event, "FeesSwept", log); err != nil { + return err + } + event.Raw = log -// ERC165 is an auto generated Go binding around an Ethereum contract. -type ERC165 struct { - ERC165Caller // Read-only binding to the contract - ERC165Transactor // Write-only binding to the contract - ERC165Filterer // Log filterer for contract events + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil } -// ERC165Caller is an auto generated read-only Go binding around an Ethereum contract. -type ERC165Caller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls +// ParseFeesSwept is a log parse operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_Admin *AdminFilterer) ParseFeesSwept(log types.Log) (*AdminFeesSwept, error) { + event := new(AdminFeesSwept) + if err := _Admin.contract.UnpackLog(event, "FeesSwept", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil } -// ERC165Transactor is an auto generated write-only Go binding around an Ethereum contract. -type ERC165Transactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} +// AdminRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the Admin contract. +type AdminRoleAdminChangedIterator struct { + Event *AdminRoleAdminChanged // Event containing the contract specifics and raw log -// ERC165Filterer is an auto generated log filtering Go binding around an Ethereum contract events. -type ERC165Filterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data -// ERC165Session is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type ERC165Session struct { - Contract *ERC165 // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration } -// ERC165CallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type ERC165CallerSession struct { - Contract *ERC165Caller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AdminRoleAdminChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(AdminRoleAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true -// ERC165TransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type ERC165TransactorSession struct { - Contract *ERC165Transactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(AdminRoleAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true -// ERC165Raw is an auto generated low-level Go binding around an Ethereum contract. -type ERC165Raw struct { - Contract *ERC165 // Generic contract binding to access the raw methods on + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } } -// ERC165CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type ERC165CallerRaw struct { - Contract *ERC165Caller // Generic read-only contract binding to access the raw methods on +// Error returns any retrieval or parsing error occurred during filtering. +func (it *AdminRoleAdminChangedIterator) Error() error { + return it.fail } -// ERC165TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type ERC165TransactorRaw struct { - Contract *ERC165Transactor // Generic write-only contract binding to access the raw methods on +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AdminRoleAdminChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil } -// NewERC165 creates a new instance of ERC165, bound to a specific deployed contract. -func NewERC165(address common.Address, backend bind.ContractBackend) (*ERC165, error) { - contract, err := bindERC165(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &ERC165{ERC165Caller: ERC165Caller{contract: contract}, ERC165Transactor: ERC165Transactor{contract: contract}, ERC165Filterer: ERC165Filterer{contract: contract}}, nil +// AdminRoleAdminChanged represents a RoleAdminChanged event raised by the Admin contract. +type AdminRoleAdminChanged struct { + Role [32]byte + PreviousAdminRole [32]byte + NewAdminRole [32]byte + Raw types.Log // Blockchain specific contextual infos } -// NewERC165Caller creates a new read-only instance of ERC165, bound to a specific deployed contract. -func NewERC165Caller(address common.Address, caller bind.ContractCaller) (*ERC165Caller, error) { - contract, err := bindERC165(address, caller, nil, nil) - if err != nil { - return nil, err +// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_Admin *AdminFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*AdminRoleAdminChangedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) } - return &ERC165Caller{contract: contract}, nil -} -// NewERC165Transactor creates a new write-only instance of ERC165, bound to a specific deployed contract. -func NewERC165Transactor(address common.Address, transactor bind.ContractTransactor) (*ERC165Transactor, error) { - contract, err := bindERC165(address, nil, transactor, nil) + logs, sub, err := _Admin.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { return nil, err } - return &ERC165Transactor{contract: contract}, nil + return &AdminRoleAdminChangedIterator{contract: _Admin.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil } -// NewERC165Filterer creates a new log filterer instance of ERC165, bound to a specific deployed contract. -func NewERC165Filterer(address common.Address, filterer bind.ContractFilterer) (*ERC165Filterer, error) { - contract, err := bindERC165(address, nil, nil, filterer) - if err != nil { - return nil, err +// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_Admin *AdminFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *AdminRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) } - return &ERC165Filterer{contract: contract}, nil -} -// bindERC165 binds a generic wrapper to an already deployed contract. -func bindERC165(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := ERC165MetaData.GetAbi() + logs, sub, err := _Admin.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { return nil, err } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_ERC165 *ERC165Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _ERC165.Contract.ERC165Caller.contract.Call(opts, result, method, params...) -} + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(AdminRoleAdminChanged) + if err := _Admin.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { + return err + } + event.Raw = log -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_ERC165 *ERC165Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _ERC165.Contract.ERC165Transactor.contract.Transfer(opts) + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil } -// Transact invokes the (paid) contract method with params as input values. -func (_ERC165 *ERC165Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _ERC165.Contract.ERC165Transactor.contract.Transact(opts, method, params...) +// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_Admin *AdminFilterer) ParseRoleAdminChanged(log types.Log) (*AdminRoleAdminChanged, error) { + event := new(AdminRoleAdminChanged) + if err := _Admin.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil } -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_ERC165 *ERC165CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _ERC165.Contract.contract.Call(opts, result, method, params...) -} +// AdminRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the Admin contract. +type AdminRoleGrantedIterator struct { + Event *AdminRoleGranted // Event containing the contract specifics and raw log -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_ERC165 *ERC165TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _ERC165.Contract.contract.Transfer(opts) -} + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data -// Transact invokes the (paid) contract method with params as input values. -func (_ERC165 *ERC165TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _ERC165.Contract.contract.Transact(opts, method, params...) + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration } -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_ERC165 *ERC165Caller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { - var out []interface{} - err := _ERC165.contract.Call(opts, &out, "supportsInterface", interfaceId) - - if err != nil { - return *new(bool), err +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AdminRoleGrantedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(AdminRoleGranted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(AdminRoleGranted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } } -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_ERC165 *ERC165Session) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _ERC165.Contract.SupportsInterface(&_ERC165.CallOpts, interfaceId) +// Error returns any retrieval or parsing error occurred during filtering. +func (it *AdminRoleGrantedIterator) Error() error { + return it.fail } -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_ERC165 *ERC165CallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _ERC165.Contract.SupportsInterface(&_ERC165.CallOpts, interfaceId) +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AdminRoleGrantedIterator) Close() error { + it.sub.Unsubscribe() + return nil } -// FastBridgeMetaData contains all meta data concerning the FastBridge contract. -var FastBridgeMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineNotExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineTooShort\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputePeriodNotPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputePeriodPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MsgValueIncorrect\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SenderIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StatusIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenNotContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransactionRelayed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositRefunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"BridgeProofDisputed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"transactionHash\",\"type\":\"bytes32\"}],\"name\":\"BridgeProofProvided\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"BridgeRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"}],\"name\":\"BridgeRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DISPUTE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_DEADLINE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROVE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"addGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"addGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"addRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"structIFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"bridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeProofs\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"timestamp\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeRelays\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeStatuses\",\"outputs\":[{\"internalType\":\"enumFastBridge.BridgeStatus\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"canClaim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"dispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"getBridgeTransaction\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originSender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destRecipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originFeeAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"internalType\":\"structIFastBridge.BridgeTransaction\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"destTxHash\",\"type\":\"bytes32\"}],\"name\":\"prove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"refund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"removeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"removeGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"removeRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Sigs: map[string]string{ - "a217fddf": "DEFAULT_ADMIN_ROLE()", - "a5bbe22b": "DISPUTE_PERIOD()", - "bf333f2c": "FEE_BPS()", - "0f5f6ed7": "FEE_RATE_MAX()", - "ccc57490": "GOVERNOR_ROLE()", - "03ed0ee5": "GUARD_ROLE()", - "820688d5": "MIN_DEADLINE_PERIOD()", - "d3cbc760": "PROVE_PERIOD()", - "926d7d7f": "RELAYER_ROLE()", - "3c4a25d0": "addGovernor(address)", - "6913a63c": "addGuard(address)", - "dd39f00d": "addRelayer(address)", - "45851694": "bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))", - "91ad5039": "bridgeProofs(bytes32)", - "8379a24f": "bridgeRelays(bytes32)", - "051287bc": "bridgeStatuses(bytes32)", - "aa9641ab": "canClaim(bytes32,address)", - "e00a83e0": "chainGasAmount()", - "41fcb612": "claim(bytes,address)", - "a3ec191a": "deployBlock()", - "add98c70": "dispute(bytes32)", - "ac11fb1a": "getBridgeTransaction(bytes)", - "248a9ca3": "getRoleAdmin(bytes32)", - "2f2ff15d": "grantRole(bytes32,address)", - "91d14854": "hasRole(bytes32,address)", - "affed0e0": "nonce()", - "58f85880": "protocolFeeRate()", - "dcf844a7": "protocolFees(address)", - "886d36ff": "prove(bytes,bytes32)", - "5eb7d946": "refund(bytes)", - "8f0d6f17": "relay(bytes)", - "eecdac88": "removeGovernor(address)", - "b6235016": "removeGuard(address)", - "60f0a5ac": "removeRelayer(address)", - "36568abe": "renounceRole(bytes32,address)", - "d547741f": "revokeRole(bytes32,address)", - "b250fe6b": "setChainGasAmount(uint256)", - "b13aa2d6": "setProtocolFeeRate(uint256)", - "01ffc9a7": "supportsInterface(bytes4)", - "06f333f2": "sweepProtocolFees(address,address)", - }, - Bin: "0x60a06040523480156200001157600080fd5b5060405162003105380380620031058339810160408190526200003491620000fe565b80620000426000826200004f565b5050436080525062000130565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16620000f4576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620000ab3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001620000f8565b5060005b92915050565b6000602082840312156200011157600080fd5b81516001600160a01b03811681146200012957600080fd5b9392505050565b608051612fb96200014c600039600061067f0152612fb96000f3fe6080604052600436106102bb5760003560e01c806391d148541161016e578063b250fe6b116100cb578063d547741f1161007f578063dd39f00d11610064578063dd39f00d14610832578063e00a83e014610852578063eecdac881461086857600080fd5b8063d547741f146107e5578063dcf844a71461080557600080fd5b8063bf333f2c116100b0578063bf333f2c14610784578063ccc574901461079b578063d3cbc760146107cf57600080fd5b8063b250fe6b14610744578063b62350161461076457600080fd5b8063aa9641ab11610122578063add98c7011610107578063add98c70146106ee578063affed0e01461070e578063b13aa2d61461072457600080fd5b8063aa9641ab146106a1578063ac11fb1a146106c157600080fd5b8063a217fddf11610153578063a217fddf14610658578063a3ec191a1461066d578063a5bbe22b146104e557600080fd5b806391d14854146105e0578063926d7d7f1461062457600080fd5b8063458516941161021c578063820688d5116101d0578063886d36ff116101b5578063886d36ff1461052b5780638f0d6f171461054b57806391ad50391461055e57600080fd5b8063820688d5146104e55780638379a24f146104fb57600080fd5b80635eb7d946116102015780635eb7d9461461048557806360f0a5ac146104a55780636913a63c146104c557600080fd5b8063458516941461045c57806358f858801461046f57600080fd5b8063248a9ca31161027357806336568abe1161025857806336568abe146103fc5780633c4a25d01461041c57806341fcb6121461043c57600080fd5b8063248a9ca3146103ac5780632f2ff15d146103dc57600080fd5b8063051287bc116102a4578063051287bc1461033757806306f333f2146103745780630f5f6ed71461039657600080fd5b806301ffc9a7146102c057806303ed0ee5146102f5575b600080fd5b3480156102cc57600080fd5b506102e06102db366004612796565b610888565b60405190151581526020015b60405180910390f35b34801561030157600080fd5b506103297f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b6040519081526020016102ec565b34801561034357600080fd5b506103676103523660046127d8565b60046020526000908152604090205460ff1681565b6040516102ec9190612820565b34801561038057600080fd5b5061039461038f366004612886565b610921565b005b3480156103a257600080fd5b5061032961271081565b3480156103b857600080fd5b506103296103c73660046127d8565b60009081526020819052604090206001015490565b3480156103e857600080fd5b506103946103f73660046128bf565b610a59565b34801561040857600080fd5b506103946104173660046128bf565b610a84565b34801561042857600080fd5b506103946104373660046128e4565b610ad5565b34801561044857600080fd5b50610394610457366004612a29565b610b7b565b61039461046a366004612aa6565b610e23565b34801561047b57600080fd5b5061032960015481565b34801561049157600080fd5b506103946104a0366004612b49565b611131565b3480156104b157600080fd5b506103946104c03660046128e4565b611294565b3480156104d157600080fd5b506103946104e03660046128e4565b611333565b3480156104f157600080fd5b5061032961070881565b34801561050757600080fd5b506102e06105163660046127d8565b60066020526000908152604090205460ff1681565b34801561053757600080fd5b50610394610546366004612b86565b6113d2565b610394610559366004612b49565b6115ce565b34801561056a57600080fd5b506105b46105793660046127d8565b6005602052600090815260409020546bffffffffffffffffffffffff8116906c0100000000000000000000000090046001600160a01b031682565b604080516bffffffffffffffffffffffff90931683526001600160a01b039091166020830152016102ec565b3480156105ec57600080fd5b506102e06105fb3660046128bf565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561063057600080fd5b506103297fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b34801561066457600080fd5b50610329600081565b34801561067957600080fd5b506103297f000000000000000000000000000000000000000000000000000000000000000081565b3480156106ad57600080fd5b506102e06106bc3660046128bf565b611883565b3480156106cd57600080fd5b506106e16106dc366004612b49565b611988565b6040516102ec9190612bcb565b3480156106fa57600080fd5b506103946107093660046127d8565b6119fb565b34801561071a57600080fd5b5061032960075481565b34801561073057600080fd5b5061039461073f3660046127d8565b611bd3565b34801561075057600080fd5b5061039461075f3660046127d8565b611d1d565b34801561077057600080fd5b5061039461077f3660046128e4565b611df3565b34801561079057600080fd5b50610329620f424081565b3480156107a757600080fd5b506103297f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b3480156107db57600080fd5b50610329610e1081565b3480156107f157600080fd5b506103946108003660046128bf565b611e92565b34801561081157600080fd5b506103296108203660046128e4565b60026020526000908152604090205481565b34801561083e57600080fd5b5061039461084d3660046128e4565b611eb7565b34801561085e57600080fd5b5061032960035481565b34801561087457600080fd5b506103946108833660046128e4565b611f56565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061091b57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff166109be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064015b60405180910390fd5b6001600160a01b038216600090815260026020526040812054908190036109e457505050565b6001600160a01b038316600081815260026020526040812055610a08908383611ff5565b604080516001600160a01b038086168252841660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b5050565b600082815260208190526040902060010154610a7481612118565b610a7e8383612125565b50505050565b6001600160a01b0381163314610ac6576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ad082826121cf565b505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610b1057600080fd5b610b3a7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5582612125565b506040516001600160a01b03821681527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5906020015b60405180910390a150565b3360009081527ffaf93c3d007e112089dc8351e013e6685ef67703975d0224b26fc45941d4f1f5602052604090205460ff16610c13576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616c6c6572206973206e6f7420612072656c6179657200000000000000000060448201526064016109b5565b815160208301206000610c2584611988565b9050600260008381526004602081905260409091205460ff1690811115610c4e57610c4e6127f1565b14610c85576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040918290208251808401909352546bffffffffffffffffffffffff811683526c0100000000000000000000000090046001600160a01b03169082018190523314610d08576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611610d55576040517f1992d0bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600460205260409020805460ff1916600317905561010082015115610db15761010082015160808301516001600160a01b031660009081526002602052604081208054909190610dab908490612ce0565b90915550505b608082015160c0830151610dcf6001600160a01b0383168783611ff5565b604080516001600160a01b03848116825260208201849052881691339188917f582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac67891015b60405180910390a450505050505050565b46816000015163ffffffff1603610e66576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a08101511580610e79575060c0810151155b15610eb0576040517fe38820c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608101516001600160a01b03161580610ed5575060808101516001600160a01b0316155b15610f0c576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f1861070842612ce0565b8161010001511015610f56576040517f04b7fcc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610f6b3083606001518460a00151612252565b90506000806001541115610f9857620f424060015483610f8b9190612cf3565b610f959190612d0a565b90505b610fa28183612d45565b915060006040518061018001604052804663ffffffff168152602001856000015163ffffffff16815260200185602001516001600160a01b0316815260200185604001516001600160a01b0316815260200185606001516001600160a01b0316815260200185608001516001600160a01b031681526020018481526020018560c0015181526020018381526020018560e001511515815260200185610100015181526020016007600081548092919061105a90612d58565b9091555090526040516110709190602001612bcb565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152828252805160208083019190912060008181526004835293909320805460ff191660011790558701518751606089015160808a015160c08b015160e08c015195985095966001600160a01b039094169587957f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a95611122958b959094909390928e92612db4565b60405180910390a35050505050565b80516020820120600061114383611988565b9050610e108161014001516111589190612ce0565b4211611190576040517fe15ff9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008381526004602081905260409091205460ff16908111156111b7576111b76127f1565b146111ee576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600460208190526040909120805460ff191660018302179055506040810151608082015161010083015160c084015160009161122e91612ce0565b90506112446001600160a01b0383168483611ff5565b604080516001600160a01b0384811682526020820184905285169187917fb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958910160405180910390a3505050505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166112cf57600080fd5b6112f97fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4826121cf565b506040516001600160a01b03821681527f10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b90602001610b70565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661136e57600080fd5b6113987f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d82612125565b506040516001600160a01b03821681527f93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f5990602001610b70565b3360009081527ffaf93c3d007e112089dc8351e013e6685ef67703975d0224b26fc45941d4f1f5602052604090205460ff1661146a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616c6c6572206973206e6f7420612072656c6179657200000000000000000060448201526064016109b5565b81516020830120600061147c84611988565b9050610e108161014001516114919190612ce0565b4211156114ca576040517f559895a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008381526004602081905260409091205460ff16908111156114f1576114f16127f1565b14611528576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526004602090815260408083208054600260ff19909116179055805180820182526bffffffffffffffffffffffff4281168252338285018181528887526005865295849020925195516001600160a01b03166c0100000000000000000000000002959091169490941790555185815284917f4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4910160405180910390a350505050565b3360009081527ffaf93c3d007e112089dc8351e013e6685ef67703975d0224b26fc45941d4f1f5602052604090205460ff16611666576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616c6c6572206973206e6f7420612072656c6179657200000000000000000060448201526064016109b5565b80516020820120600061167883611988565b90504663ffffffff16816020015163ffffffff16146116c3576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806101400151421115611702576040517f559895a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205460ff161561174b576040517fbef7bb7d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660205260409020805460ff19166001179055606081015160a082015160e08301516003546101208501516117945750600061178e848484612252565b50611805565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b038416016117d85761178e84846117d38486612ce0565b612252565b6117e3848484612252565b506118038473eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee83612252565b505b845160808087015160a08089015160c0808b015160e08c01516040805163ffffffff90991689526001600160a01b0396871660208a0152938616938801939093526060870152938501528301849052861691339189917ff8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c9101610e12565b6000600260008481526004602081905260409091205460ff16908111156118ac576118ac6127f1565b146118e3576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600560209081526040918290208251808401909352546bffffffffffffffffffffffff811683526001600160a01b036c010000000000000000000000009091048116918301829052841614611969576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611949350505050565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201528251909161091b9184018101908401612e65565b3360009081527f92bf2f06c618f6add65571bf52eb90d22c9b52fd65028daa87260b82998b30bd602052604090205460ff16611a93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f43616c6c6572206973206e6f742061206775617264000000000000000000000060448201526064016109b5565b600260008281526004602081905260409091205460ff1690811115611aba57611aba6127f1565b14611af1576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600560209081526040918290208251808401909352546bffffffffffffffffffffffff8082168085526c010000000000000000000000009092046001600160a01b03169390920192909252610708914203161115611b80576040517f3e908aac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460209081526040808320805460ff19166001179055600590915280822082905551339183917f0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad49190a350565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16611c6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064016109b5565b612710811115611cd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064016109b5565b600180549082905560408051828152602081018490527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a15050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16611db5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064016109b5565b600380549082905560408051828152602081018490527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa9101611d11565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611e2e57600080fd5b611e587f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d826121cf565b506040516001600160a01b03821681527f59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d04890602001610b70565b600082815260208190526040902060010154611ead81612118565b610a7e83836121cf565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611ef257600080fd5b611f1c7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc482612125565b506040516001600160a01b03821681527f03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c590602001610b70565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611f9157600080fd5b611fbb7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55826121cf565b506040516001600160a01b03821681527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b90602001610b70565b306001600160a01b0383160361200a57505050565b8060000361201757505050565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03841601612104576000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612094576040519150601f19603f3d011682016040523d82523d6000602084013e612099565b606091505b5050905080610a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c65640000000000000000000000000060448201526064016109b5565b610ad06001600160a01b0384168383612422565b6121228133612496565b50565b6000828152602081815260408083206001600160a01b038516845290915281205460ff166121c7576000838152602081815260408083206001600160a01b03861684529091529020805460ff1916600117905561217f3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161091b565b50600061091b565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16156121c7576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161091b565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146123bb5761228a836001600160a01b0316612502565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528416906370a0823190602401602060405180830381865afa1580156122e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061230d9190612f31565b90506123246001600160a01b0384163386856125a8565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528291908516906370a0823190602401602060405180830381865afa158015612386573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123aa9190612f31565b6123b49190612d45565b905061241b565b3482146123f4576040517f81de0bf300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0384163014612418576124186001600160a01b0384168584611ff5565b50345b9392505050565b6040516001600160a01b03838116602483015260448201839052610ad091859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506125e1565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610a55576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602481018390526044016109b5565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03821601612564576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03163b600003612122576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038481166024830152838116604483015260648201839052610a7e9186918216906323b872dd9060840161244f565b60006125f66001600160a01b0384168361265d565b9050805160001415801561261b5750808060200190518101906126199190612f4a565b155b15610ad0576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024016109b5565b606061241b8383600084600080856001600160a01b031684866040516126839190612f67565b60006040518083038185875af1925050503d80600081146126c0576040519150601f19603f3d011682016040523d82523d6000602084013e6126c5565b606091505b50915091506126d58683836126df565b9695505050505050565b6060826126f4576126ef82612754565b61241b565b815115801561270b57506001600160a01b0384163b155b1561274d576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016109b5565b508061241b565b8051156127645780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602082840312156127a857600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461241b57600080fd5b6000602082840312156127ea57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016005831061285b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6001600160a01b038116811461212257600080fd5b803561288181612861565b919050565b6000806040838503121561289957600080fd5b82356128a481612861565b915060208301356128b481612861565b809150509250929050565b600080604083850312156128d257600080fd5b8235915060208301356128b481612861565b6000602082840312156128f657600080fd5b813561241b81612861565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171561295457612954612901565b60405290565b604051610180810167ffffffffffffffff8111828210171561295457612954612901565b600082601f83011261298f57600080fd5b813567ffffffffffffffff808211156129aa576129aa612901565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156129f0576129f0612901565b81604052838152866020858801011115612a0957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215612a3c57600080fd5b823567ffffffffffffffff811115612a5357600080fd5b612a5f8582860161297e565b92505060208301356128b481612861565b63ffffffff8116811461212257600080fd5b803561288181612a70565b801515811461212257600080fd5b803561288181612a8d565b60006101208284031215612ab957600080fd5b612ac1612930565b612aca83612a82565b8152612ad860208401612876565b6020820152612ae960408401612876565b6040820152612afa60608401612876565b6060820152612b0b60808401612876565b608082015260a083013560a082015260c083013560c0820152612b3060e08401612a9b565b60e0820152610100928301359281019290925250919050565b600060208284031215612b5b57600080fd5b813567ffffffffffffffff811115612b7257600080fd5b612b7e8482850161297e565b949350505050565b60008060408385031215612b9957600080fd5b823567ffffffffffffffff811115612bb057600080fd5b612bbc8582860161297e565b95602094909401359450505050565b815163ffffffff16815261018081016020830151612bf1602084018263ffffffff169052565b506040830151612c0c60408401826001600160a01b03169052565b506060830151612c2760608401826001600160a01b03169052565b506080830151612c4260808401826001600160a01b03169052565b5060a0830151612c5d60a08401826001600160a01b03169052565b5060c083015160c083015260e083015160e083015261010080840151818401525061012080840151612c928285018215159052565b5050610140838101519083015261016092830151929091019190915290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561091b5761091b612cb1565b808202811582820484141761091b5761091b612cb1565b600082612d40577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561091b5761091b612cb1565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612d8957612d89612cb1565b5060010190565b60005b83811015612dab578181015183820152602001612d93565b50506000910152565b60e08152600088518060e0840152610100612dd58282860160208e01612d90565b63ffffffff9990991660208401526001600160a01b039788166040840152959096166060820152608081019390935260a0830191909152151560c0820152601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190910192915050565b805161288181612a70565b805161288181612861565b805161288181612a8d565b60006101808284031215612e7857600080fd5b612e8061295a565b612e8983612e44565b8152612e9760208401612e44565b6020820152612ea860408401612e4f565b6040820152612eb960608401612e4f565b6060820152612eca60808401612e4f565b6080820152612edb60a08401612e4f565b60a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120612f0e818501612e5a565b908201526101408381015190820152610160928301519281019290925250919050565b600060208284031215612f4357600080fd5b5051919050565b600060208284031215612f5c57600080fd5b815161241b81612a8d565b60008251612f79818460208701612d90565b919091019291505056fea26469706673582212201d3a10322561f18b095a55071d44fc12bf9e48f853c53f8cfe4c3915d4f3009764736f6c63430008140033", +// AdminRoleGranted represents a RoleGranted event raised by the Admin contract. +type AdminRoleGranted struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos } -// FastBridgeABI is the input ABI used to generate the binding from. -// Deprecated: Use FastBridgeMetaData.ABI instead. -var FastBridgeABI = FastBridgeMetaData.ABI - -// Deprecated: Use FastBridgeMetaData.Sigs instead. -// FastBridgeFuncSigs maps the 4-byte function signature to its string representation. -var FastBridgeFuncSigs = FastBridgeMetaData.Sigs - -// FastBridgeBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use FastBridgeMetaData.Bin instead. -var FastBridgeBin = FastBridgeMetaData.Bin +// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_Admin *AdminFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*AdminRoleGrantedIterator, error) { -// DeployFastBridge deploys a new Ethereum contract, binding an instance of FastBridge to it. -func DeployFastBridge(auth *bind.TransactOpts, backend bind.ContractBackend, _owner common.Address) (common.Address, *types.Transaction, *FastBridge, error) { - parsed, err := FastBridgeMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(FastBridgeBin), backend, _owner) + logs, sub, err := _Admin.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) if err != nil { - return common.Address{}, nil, nil, err + return nil, err } - return address, tx, &FastBridge{FastBridgeCaller: FastBridgeCaller{contract: contract}, FastBridgeTransactor: FastBridgeTransactor{contract: contract}, FastBridgeFilterer: FastBridgeFilterer{contract: contract}}, nil -} - -// FastBridge is an auto generated Go binding around an Ethereum contract. -type FastBridge struct { - FastBridgeCaller // Read-only binding to the contract - FastBridgeTransactor // Write-only binding to the contract - FastBridgeFilterer // Log filterer for contract events + return &AdminRoleGrantedIterator{contract: _Admin.contract, event: "RoleGranted", logs: logs, sub: sub}, nil } -// FastBridgeCaller is an auto generated read-only Go binding around an Ethereum contract. -type FastBridgeCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} +// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_Admin *AdminFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *AdminRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { -// FastBridgeTransactor is an auto generated write-only Go binding around an Ethereum contract. -type FastBridgeTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } -// FastBridgeFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type FastBridgeFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} + logs, sub, err := _Admin.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(AdminRoleGranted) + if err := _Admin.contract.UnpackLog(event, "RoleGranted", log); err != nil { + return err + } + event.Raw = log -// FastBridgeSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type FastBridgeSession struct { - Contract *FastBridge // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil } -// FastBridgeCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type FastBridgeCallerSession struct { - Contract *FastBridgeCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session +// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_Admin *AdminFilterer) ParseRoleGranted(log types.Log) (*AdminRoleGranted, error) { + event := new(AdminRoleGranted) + if err := _Admin.contract.UnpackLog(event, "RoleGranted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil } -// FastBridgeTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type FastBridgeTransactorSession struct { - Contract *FastBridgeTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +// AdminRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the Admin contract. +type AdminRoleRevokedIterator struct { + Event *AdminRoleRevoked // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration } -// FastBridgeRaw is an auto generated low-level Go binding around an Ethereum contract. -type FastBridgeRaw struct { - Contract *FastBridge // Generic contract binding to access the raw methods on +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AdminRoleRevokedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(AdminRoleRevoked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(AdminRoleRevoked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } } -// FastBridgeCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type FastBridgeCallerRaw struct { - Contract *FastBridgeCaller // Generic read-only contract binding to access the raw methods on +// Error returns any retrieval or parsing error occurred during filtering. +func (it *AdminRoleRevokedIterator) Error() error { + return it.fail } -// FastBridgeTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type FastBridgeTransactorRaw struct { - Contract *FastBridgeTransactor // Generic write-only contract binding to access the raw methods on +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AdminRoleRevokedIterator) Close() error { + it.sub.Unsubscribe() + return nil } -// NewFastBridge creates a new instance of FastBridge, bound to a specific deployed contract. -func NewFastBridge(address common.Address, backend bind.ContractBackend) (*FastBridge, error) { - contract, err := bindFastBridge(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &FastBridge{FastBridgeCaller: FastBridgeCaller{contract: contract}, FastBridgeTransactor: FastBridgeTransactor{contract: contract}, FastBridgeFilterer: FastBridgeFilterer{contract: contract}}, nil +// AdminRoleRevoked represents a RoleRevoked event raised by the Admin contract. +type AdminRoleRevoked struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos } -// NewFastBridgeCaller creates a new read-only instance of FastBridge, bound to a specific deployed contract. -func NewFastBridgeCaller(address common.Address, caller bind.ContractCaller) (*FastBridgeCaller, error) { - contract, err := bindFastBridge(address, caller, nil, nil) - if err != nil { - return nil, err +// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_Admin *AdminFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*AdminRoleRevokedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) } - return &FastBridgeCaller{contract: contract}, nil -} -// NewFastBridgeTransactor creates a new write-only instance of FastBridge, bound to a specific deployed contract. -func NewFastBridgeTransactor(address common.Address, transactor bind.ContractTransactor) (*FastBridgeTransactor, error) { - contract, err := bindFastBridge(address, nil, transactor, nil) + logs, sub, err := _Admin.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) if err != nil { return nil, err } - return &FastBridgeTransactor{contract: contract}, nil + return &AdminRoleRevokedIterator{contract: _Admin.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil } -// NewFastBridgeFilterer creates a new log filterer instance of FastBridge, bound to a specific deployed contract. -func NewFastBridgeFilterer(address common.Address, filterer bind.ContractFilterer) (*FastBridgeFilterer, error) { - contract, err := bindFastBridge(address, nil, nil, filterer) +// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_Admin *AdminFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *AdminRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _Admin.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) if err != nil { return nil, err } - return &FastBridgeFilterer{contract: contract}, nil + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(AdminRoleRevoked) + if err := _Admin.contract.UnpackLog(event, "RoleRevoked", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil } -// bindFastBridge binds a generic wrapper to an already deployed contract. -func bindFastBridge(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := FastBridgeMetaData.GetAbi() - if err != nil { +// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_Admin *AdminFilterer) ParseRoleRevoked(log types.Log) (*AdminRoleRevoked, error) { + event := new(AdminRoleRevoked) + if err := _Admin.contract.UnpackLog(event, "RoleRevoked", log); err != nil { return nil, err } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil + event.Raw = log + return event, nil } -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_FastBridge *FastBridgeRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _FastBridge.Contract.FastBridgeCaller.contract.Call(opts, result, method, params...) +// ContextMetaData contains all meta data concerning the Context contract. +var ContextMetaData = &bind.MetaData{ + ABI: "[]", } -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_FastBridge *FastBridgeRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _FastBridge.Contract.FastBridgeTransactor.contract.Transfer(opts) -} +// ContextABI is the input ABI used to generate the binding from. +// Deprecated: Use ContextMetaData.ABI instead. +var ContextABI = ContextMetaData.ABI -// Transact invokes the (paid) contract method with params as input values. -func (_FastBridge *FastBridgeRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _FastBridge.Contract.FastBridgeTransactor.contract.Transact(opts, method, params...) +// Context is an auto generated Go binding around an Ethereum contract. +type Context struct { + ContextCaller // Read-only binding to the contract + ContextTransactor // Write-only binding to the contract + ContextFilterer // Log filterer for contract events } -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_FastBridge *FastBridgeCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _FastBridge.Contract.contract.Call(opts, result, method, params...) +// ContextCaller is an auto generated read-only Go binding around an Ethereum contract. +type ContextCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_FastBridge *FastBridgeTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _FastBridge.Contract.contract.Transfer(opts) +// ContextTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ContextTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// Transact invokes the (paid) contract method with params as input values. -func (_FastBridge *FastBridgeTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _FastBridge.Contract.contract.Transact(opts, method, params...) +// ContextFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ContextFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. -// -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) +// ContextSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ContextSession struct { + Contract *Context // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} - return out0, err +// ContextCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ContextCallerSession struct { + Contract *ContextCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} +// ContextTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ContextTransactorSession struct { + Contract *ContextTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. -// -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeSession) DEFAULTADMINROLE() ([32]byte, error) { - return _FastBridge.Contract.DEFAULTADMINROLE(&_FastBridge.CallOpts) +// ContextRaw is an auto generated low-level Go binding around an Ethereum contract. +type ContextRaw struct { + Contract *Context // Generic contract binding to access the raw methods on } -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. -// -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeCallerSession) DEFAULTADMINROLE() ([32]byte, error) { - return _FastBridge.Contract.DEFAULTADMINROLE(&_FastBridge.CallOpts) +// ContextCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ContextCallerRaw struct { + Contract *ContextCaller // Generic read-only contract binding to access the raw methods on } -// DISPUTEPERIOD is a free data retrieval call binding the contract method 0xa5bbe22b. -// -// Solidity: function DISPUTE_PERIOD() view returns(uint256) -func (_FastBridge *FastBridgeCaller) DISPUTEPERIOD(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "DISPUTE_PERIOD") +// ContextTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ContextTransactorRaw struct { + Contract *ContextTransactor // Generic write-only contract binding to access the raw methods on +} +// NewContext creates a new instance of Context, bound to a specific deployed contract. +func NewContext(address common.Address, backend bind.ContractBackend) (*Context, error) { + contract, err := bindContext(address, backend, backend, backend) if err != nil { - return *new(*big.Int), err + return nil, err } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - + return &Context{ContextCaller: ContextCaller{contract: contract}, ContextTransactor: ContextTransactor{contract: contract}, ContextFilterer: ContextFilterer{contract: contract}}, nil } -// DISPUTEPERIOD is a free data retrieval call binding the contract method 0xa5bbe22b. -// -// Solidity: function DISPUTE_PERIOD() view returns(uint256) -func (_FastBridge *FastBridgeSession) DISPUTEPERIOD() (*big.Int, error) { - return _FastBridge.Contract.DISPUTEPERIOD(&_FastBridge.CallOpts) +// NewContextCaller creates a new read-only instance of Context, bound to a specific deployed contract. +func NewContextCaller(address common.Address, caller bind.ContractCaller) (*ContextCaller, error) { + contract, err := bindContext(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ContextCaller{contract: contract}, nil } -// DISPUTEPERIOD is a free data retrieval call binding the contract method 0xa5bbe22b. -// -// Solidity: function DISPUTE_PERIOD() view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) DISPUTEPERIOD() (*big.Int, error) { - return _FastBridge.Contract.DISPUTEPERIOD(&_FastBridge.CallOpts) +// NewContextTransactor creates a new write-only instance of Context, bound to a specific deployed contract. +func NewContextTransactor(address common.Address, transactor bind.ContractTransactor) (*ContextTransactor, error) { + contract, err := bindContext(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ContextTransactor{contract: contract}, nil } -// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. -// -// Solidity: function FEE_BPS() view returns(uint256) -func (_FastBridge *FastBridgeCaller) FEEBPS(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "FEE_BPS") +// NewContextFilterer creates a new log filterer instance of Context, bound to a specific deployed contract. +func NewContextFilterer(address common.Address, filterer bind.ContractFilterer) (*ContextFilterer, error) { + contract, err := bindContext(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ContextFilterer{contract: contract}, nil +} +// bindContext binds a generic wrapper to an already deployed contract. +func bindContext(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ContextMetaData.GetAbi() if err != nil { - return *new(*big.Int), err + return nil, err } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Context *ContextRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Context.Contract.ContextCaller.contract.Call(opts, result, method, params...) +} - return out0, err +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Context *ContextRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Context.Contract.ContextTransactor.contract.Transfer(opts) +} +// Transact invokes the (paid) contract method with params as input values. +func (_Context *ContextRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Context.Contract.ContextTransactor.contract.Transact(opts, method, params...) } -// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. -// -// Solidity: function FEE_BPS() view returns(uint256) -func (_FastBridge *FastBridgeSession) FEEBPS() (*big.Int, error) { - return _FastBridge.Contract.FEEBPS(&_FastBridge.CallOpts) +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Context *ContextCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Context.Contract.contract.Call(opts, result, method, params...) } -// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. -// -// Solidity: function FEE_BPS() view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) FEEBPS() (*big.Int, error) { - return _FastBridge.Contract.FEEBPS(&_FastBridge.CallOpts) +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Context *ContextTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Context.Contract.contract.Transfer(opts) } -// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. -// -// Solidity: function FEE_RATE_MAX() view returns(uint256) -func (_FastBridge *FastBridgeCaller) FEERATEMAX(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "FEE_RATE_MAX") +// Transact invokes the (paid) contract method with params as input values. +func (_Context *ContextTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Context.Contract.contract.Transact(opts, method, params...) +} - if err != nil { - return *new(*big.Int), err - } +// ERC165MetaData contains all meta data concerning the ERC165 contract. +var ERC165MetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "01ffc9a7": "supportsInterface(bytes4)", + }, +} - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) +// ERC165ABI is the input ABI used to generate the binding from. +// Deprecated: Use ERC165MetaData.ABI instead. +var ERC165ABI = ERC165MetaData.ABI - return out0, err +// Deprecated: Use ERC165MetaData.Sigs instead. +// ERC165FuncSigs maps the 4-byte function signature to its string representation. +var ERC165FuncSigs = ERC165MetaData.Sigs +// ERC165 is an auto generated Go binding around an Ethereum contract. +type ERC165 struct { + ERC165Caller // Read-only binding to the contract + ERC165Transactor // Write-only binding to the contract + ERC165Filterer // Log filterer for contract events } -// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. -// -// Solidity: function FEE_RATE_MAX() view returns(uint256) -func (_FastBridge *FastBridgeSession) FEERATEMAX() (*big.Int, error) { - return _FastBridge.Contract.FEERATEMAX(&_FastBridge.CallOpts) +// ERC165Caller is an auto generated read-only Go binding around an Ethereum contract. +type ERC165Caller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. -// -// Solidity: function FEE_RATE_MAX() view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) FEERATEMAX() (*big.Int, error) { - return _FastBridge.Contract.FEERATEMAX(&_FastBridge.CallOpts) +// ERC165Transactor is an auto generated write-only Go binding around an Ethereum contract. +type ERC165Transactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. -// -// Solidity: function GOVERNOR_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeCaller) GOVERNORROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "GOVERNOR_ROLE") +// ERC165Filterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ERC165Filterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} - if err != nil { - return *new([32]byte), err - } +// ERC165Session is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ERC165Session struct { + Contract *ERC165 // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) +// ERC165CallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ERC165CallerSession struct { + Contract *ERC165Caller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} - return out0, err +// ERC165TransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ERC165TransactorSession struct { + Contract *ERC165Transactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} +// ERC165Raw is an auto generated low-level Go binding around an Ethereum contract. +type ERC165Raw struct { + Contract *ERC165 // Generic contract binding to access the raw methods on } -// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. -// -// Solidity: function GOVERNOR_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeSession) GOVERNORROLE() ([32]byte, error) { - return _FastBridge.Contract.GOVERNORROLE(&_FastBridge.CallOpts) +// ERC165CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ERC165CallerRaw struct { + Contract *ERC165Caller // Generic read-only contract binding to access the raw methods on } -// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. -// -// Solidity: function GOVERNOR_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeCallerSession) GOVERNORROLE() ([32]byte, error) { - return _FastBridge.Contract.GOVERNORROLE(&_FastBridge.CallOpts) +// ERC165TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ERC165TransactorRaw struct { + Contract *ERC165Transactor // Generic write-only contract binding to access the raw methods on } -// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. -// -// Solidity: function GUARD_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeCaller) GUARDROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "GUARD_ROLE") - +// NewERC165 creates a new instance of ERC165, bound to a specific deployed contract. +func NewERC165(address common.Address, backend bind.ContractBackend) (*ERC165, error) { + contract, err := bindERC165(address, backend, backend, backend) if err != nil { - return *new([32]byte), err + return nil, err } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - + return &ERC165{ERC165Caller: ERC165Caller{contract: contract}, ERC165Transactor: ERC165Transactor{contract: contract}, ERC165Filterer: ERC165Filterer{contract: contract}}, nil } -// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. -// -// Solidity: function GUARD_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeSession) GUARDROLE() ([32]byte, error) { - return _FastBridge.Contract.GUARDROLE(&_FastBridge.CallOpts) +// NewERC165Caller creates a new read-only instance of ERC165, bound to a specific deployed contract. +func NewERC165Caller(address common.Address, caller bind.ContractCaller) (*ERC165Caller, error) { + contract, err := bindERC165(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ERC165Caller{contract: contract}, nil } -// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. -// -// Solidity: function GUARD_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeCallerSession) GUARDROLE() ([32]byte, error) { - return _FastBridge.Contract.GUARDROLE(&_FastBridge.CallOpts) +// NewERC165Transactor creates a new write-only instance of ERC165, bound to a specific deployed contract. +func NewERC165Transactor(address common.Address, transactor bind.ContractTransactor) (*ERC165Transactor, error) { + contract, err := bindERC165(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ERC165Transactor{contract: contract}, nil } -// MINDEADLINEPERIOD is a free data retrieval call binding the contract method 0x820688d5. -// -// Solidity: function MIN_DEADLINE_PERIOD() view returns(uint256) -func (_FastBridge *FastBridgeCaller) MINDEADLINEPERIOD(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "MIN_DEADLINE_PERIOD") +// NewERC165Filterer creates a new log filterer instance of ERC165, bound to a specific deployed contract. +func NewERC165Filterer(address common.Address, filterer bind.ContractFilterer) (*ERC165Filterer, error) { + contract, err := bindERC165(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ERC165Filterer{contract: contract}, nil +} +// bindERC165 binds a generic wrapper to an already deployed contract. +func bindERC165(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ERC165MetaData.GetAbi() if err != nil { - return *new(*big.Int), err + return nil, err } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ERC165 *ERC165Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ERC165.Contract.ERC165Caller.contract.Call(opts, result, method, params...) +} - return out0, err +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ERC165 *ERC165Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC165.Contract.ERC165Transactor.contract.Transfer(opts) +} +// Transact invokes the (paid) contract method with params as input values. +func (_ERC165 *ERC165Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ERC165.Contract.ERC165Transactor.contract.Transact(opts, method, params...) } -// MINDEADLINEPERIOD is a free data retrieval call binding the contract method 0x820688d5. -// -// Solidity: function MIN_DEADLINE_PERIOD() view returns(uint256) -func (_FastBridge *FastBridgeSession) MINDEADLINEPERIOD() (*big.Int, error) { - return _FastBridge.Contract.MINDEADLINEPERIOD(&_FastBridge.CallOpts) +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ERC165 *ERC165CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ERC165.Contract.contract.Call(opts, result, method, params...) } -// MINDEADLINEPERIOD is a free data retrieval call binding the contract method 0x820688d5. -// -// Solidity: function MIN_DEADLINE_PERIOD() view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) MINDEADLINEPERIOD() (*big.Int, error) { - return _FastBridge.Contract.MINDEADLINEPERIOD(&_FastBridge.CallOpts) +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ERC165 *ERC165TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC165.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ERC165 *ERC165TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ERC165.Contract.contract.Transact(opts, method, params...) } -// PROVEPERIOD is a free data retrieval call binding the contract method 0xd3cbc760. +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: function PROVE_PERIOD() view returns(uint256) -func (_FastBridge *FastBridgeCaller) PROVEPERIOD(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_ERC165 *ERC165Caller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "PROVE_PERIOD") + err := _ERC165.contract.Call(opts, &out, "supportsInterface", interfaceId) if err != nil { - return *new(*big.Int), err + return *new(bool), err } - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) return out0, err } -// PROVEPERIOD is a free data retrieval call binding the contract method 0xd3cbc760. +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: function PROVE_PERIOD() view returns(uint256) -func (_FastBridge *FastBridgeSession) PROVEPERIOD() (*big.Int, error) { - return _FastBridge.Contract.PROVEPERIOD(&_FastBridge.CallOpts) +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_ERC165 *ERC165Session) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _ERC165.Contract.SupportsInterface(&_ERC165.CallOpts, interfaceId) } -// PROVEPERIOD is a free data retrieval call binding the contract method 0xd3cbc760. +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: function PROVE_PERIOD() view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) PROVEPERIOD() (*big.Int, error) { - return _FastBridge.Contract.PROVEPERIOD(&_FastBridge.CallOpts) +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_ERC165 *ERC165CallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _ERC165.Contract.SupportsInterface(&_ERC165.CallOpts, interfaceId) } -// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. -// -// Solidity: function RELAYER_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeCaller) RELAYERROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "RELAYER_ROLE") +// EnumerableSetMetaData contains all meta data concerning the EnumerableSet contract. +var EnumerableSetMetaData = &bind.MetaData{ + ABI: "[]", + Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212200d8618a82dfc0c2e00136a6baf933d53111fd9bd0c5433b637ac80498bb32ba464736f6c63430008140033", +} - if err != nil { - return *new([32]byte), err - } +// EnumerableSetABI is the input ABI used to generate the binding from. +// Deprecated: Use EnumerableSetMetaData.ABI instead. +var EnumerableSetABI = EnumerableSetMetaData.ABI - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) +// EnumerableSetBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use EnumerableSetMetaData.Bin instead. +var EnumerableSetBin = EnumerableSetMetaData.Bin - return out0, err +// DeployEnumerableSet deploys a new Ethereum contract, binding an instance of EnumerableSet to it. +func DeployEnumerableSet(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *EnumerableSet, error) { + parsed, err := EnumerableSetMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(EnumerableSetBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &EnumerableSet{EnumerableSetCaller: EnumerableSetCaller{contract: contract}, EnumerableSetTransactor: EnumerableSetTransactor{contract: contract}, EnumerableSetFilterer: EnumerableSetFilterer{contract: contract}}, nil } -// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. -// -// Solidity: function RELAYER_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeSession) RELAYERROLE() ([32]byte, error) { - return _FastBridge.Contract.RELAYERROLE(&_FastBridge.CallOpts) +// EnumerableSet is an auto generated Go binding around an Ethereum contract. +type EnumerableSet struct { + EnumerableSetCaller // Read-only binding to the contract + EnumerableSetTransactor // Write-only binding to the contract + EnumerableSetFilterer // Log filterer for contract events } -// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. -// -// Solidity: function RELAYER_ROLE() view returns(bytes32) -func (_FastBridge *FastBridgeCallerSession) RELAYERROLE() ([32]byte, error) { - return _FastBridge.Contract.RELAYERROLE(&_FastBridge.CallOpts) +// EnumerableSetCaller is an auto generated read-only Go binding around an Ethereum contract. +type EnumerableSetCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// BridgeProofs is a free data retrieval call binding the contract method 0x91ad5039. -// -// Solidity: function bridgeProofs(bytes32 ) view returns(uint96 timestamp, address relayer) -func (_FastBridge *FastBridgeCaller) BridgeProofs(opts *bind.CallOpts, arg0 [32]byte) (struct { - Timestamp *big.Int - Relayer common.Address -}, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "bridgeProofs", arg0) +// EnumerableSetTransactor is an auto generated write-only Go binding around an Ethereum contract. +type EnumerableSetTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} - outstruct := new(struct { - Timestamp *big.Int - Relayer common.Address - }) - if err != nil { - return *outstruct, err - } +// EnumerableSetFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type EnumerableSetFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} - outstruct.Timestamp = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - outstruct.Relayer = *abi.ConvertType(out[1], new(common.Address)).(*common.Address) +// EnumerableSetSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type EnumerableSetSession struct { + Contract *EnumerableSet // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} - return *outstruct, err +// EnumerableSetCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type EnumerableSetCallerSession struct { + Contract *EnumerableSetCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} +// EnumerableSetTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type EnumerableSetTransactorSession struct { + Contract *EnumerableSetTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// BridgeProofs is a free data retrieval call binding the contract method 0x91ad5039. -// -// Solidity: function bridgeProofs(bytes32 ) view returns(uint96 timestamp, address relayer) -func (_FastBridge *FastBridgeSession) BridgeProofs(arg0 [32]byte) (struct { - Timestamp *big.Int - Relayer common.Address -}, error) { - return _FastBridge.Contract.BridgeProofs(&_FastBridge.CallOpts, arg0) +// EnumerableSetRaw is an auto generated low-level Go binding around an Ethereum contract. +type EnumerableSetRaw struct { + Contract *EnumerableSet // Generic contract binding to access the raw methods on } -// BridgeProofs is a free data retrieval call binding the contract method 0x91ad5039. -// -// Solidity: function bridgeProofs(bytes32 ) view returns(uint96 timestamp, address relayer) -func (_FastBridge *FastBridgeCallerSession) BridgeProofs(arg0 [32]byte) (struct { - Timestamp *big.Int - Relayer common.Address -}, error) { - return _FastBridge.Contract.BridgeProofs(&_FastBridge.CallOpts, arg0) +// EnumerableSetCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type EnumerableSetCallerRaw struct { + Contract *EnumerableSetCaller // Generic read-only contract binding to access the raw methods on } -// BridgeRelays is a free data retrieval call binding the contract method 0x8379a24f. -// -// Solidity: function bridgeRelays(bytes32 ) view returns(bool) -func (_FastBridge *FastBridgeCaller) BridgeRelays(opts *bind.CallOpts, arg0 [32]byte) (bool, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "bridgeRelays", arg0) +// EnumerableSetTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type EnumerableSetTransactorRaw struct { + Contract *EnumerableSetTransactor // Generic write-only contract binding to access the raw methods on +} +// NewEnumerableSet creates a new instance of EnumerableSet, bound to a specific deployed contract. +func NewEnumerableSet(address common.Address, backend bind.ContractBackend) (*EnumerableSet, error) { + contract, err := bindEnumerableSet(address, backend, backend, backend) if err != nil { - return *new(bool), err + return nil, err } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - + return &EnumerableSet{EnumerableSetCaller: EnumerableSetCaller{contract: contract}, EnumerableSetTransactor: EnumerableSetTransactor{contract: contract}, EnumerableSetFilterer: EnumerableSetFilterer{contract: contract}}, nil } -// BridgeRelays is a free data retrieval call binding the contract method 0x8379a24f. -// -// Solidity: function bridgeRelays(bytes32 ) view returns(bool) -func (_FastBridge *FastBridgeSession) BridgeRelays(arg0 [32]byte) (bool, error) { - return _FastBridge.Contract.BridgeRelays(&_FastBridge.CallOpts, arg0) +// NewEnumerableSetCaller creates a new read-only instance of EnumerableSet, bound to a specific deployed contract. +func NewEnumerableSetCaller(address common.Address, caller bind.ContractCaller) (*EnumerableSetCaller, error) { + contract, err := bindEnumerableSet(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &EnumerableSetCaller{contract: contract}, nil } -// BridgeRelays is a free data retrieval call binding the contract method 0x8379a24f. -// -// Solidity: function bridgeRelays(bytes32 ) view returns(bool) -func (_FastBridge *FastBridgeCallerSession) BridgeRelays(arg0 [32]byte) (bool, error) { - return _FastBridge.Contract.BridgeRelays(&_FastBridge.CallOpts, arg0) +// NewEnumerableSetTransactor creates a new write-only instance of EnumerableSet, bound to a specific deployed contract. +func NewEnumerableSetTransactor(address common.Address, transactor bind.ContractTransactor) (*EnumerableSetTransactor, error) { + contract, err := bindEnumerableSet(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &EnumerableSetTransactor{contract: contract}, nil } -// BridgeStatuses is a free data retrieval call binding the contract method 0x051287bc. -// -// Solidity: function bridgeStatuses(bytes32 ) view returns(uint8) -func (_FastBridge *FastBridgeCaller) BridgeStatuses(opts *bind.CallOpts, arg0 [32]byte) (uint8, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "bridgeStatuses", arg0) - +// NewEnumerableSetFilterer creates a new log filterer instance of EnumerableSet, bound to a specific deployed contract. +func NewEnumerableSetFilterer(address common.Address, filterer bind.ContractFilterer) (*EnumerableSetFilterer, error) { + contract, err := bindEnumerableSet(address, nil, nil, filterer) if err != nil { - return *new(uint8), err + return nil, err } + return &EnumerableSetFilterer{contract: contract}, nil +} - out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) - - return out0, err +// bindEnumerableSet binds a generic wrapper to an already deployed contract. +func bindEnumerableSet(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := EnumerableSetMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_EnumerableSet *EnumerableSetRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _EnumerableSet.Contract.EnumerableSetCaller.contract.Call(opts, result, method, params...) } -// BridgeStatuses is a free data retrieval call binding the contract method 0x051287bc. -// -// Solidity: function bridgeStatuses(bytes32 ) view returns(uint8) -func (_FastBridge *FastBridgeSession) BridgeStatuses(arg0 [32]byte) (uint8, error) { - return _FastBridge.Contract.BridgeStatuses(&_FastBridge.CallOpts, arg0) +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_EnumerableSet *EnumerableSetRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _EnumerableSet.Contract.EnumerableSetTransactor.contract.Transfer(opts) } -// BridgeStatuses is a free data retrieval call binding the contract method 0x051287bc. -// -// Solidity: function bridgeStatuses(bytes32 ) view returns(uint8) -func (_FastBridge *FastBridgeCallerSession) BridgeStatuses(arg0 [32]byte) (uint8, error) { - return _FastBridge.Contract.BridgeStatuses(&_FastBridge.CallOpts, arg0) +// Transact invokes the (paid) contract method with params as input values. +func (_EnumerableSet *EnumerableSetRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _EnumerableSet.Contract.EnumerableSetTransactor.contract.Transact(opts, method, params...) } -// CanClaim is a free data retrieval call binding the contract method 0xaa9641ab. -// -// Solidity: function canClaim(bytes32 transactionId, address relayer) view returns(bool) -func (_FastBridge *FastBridgeCaller) CanClaim(opts *bind.CallOpts, transactionId [32]byte, relayer common.Address) (bool, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "canClaim", transactionId, relayer) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_EnumerableSet *EnumerableSetCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _EnumerableSet.Contract.contract.Call(opts, result, method, params...) +} +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_EnumerableSet *EnumerableSetTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _EnumerableSet.Contract.contract.Transfer(opts) } -// CanClaim is a free data retrieval call binding the contract method 0xaa9641ab. -// -// Solidity: function canClaim(bytes32 transactionId, address relayer) view returns(bool) -func (_FastBridge *FastBridgeSession) CanClaim(transactionId [32]byte, relayer common.Address) (bool, error) { - return _FastBridge.Contract.CanClaim(&_FastBridge.CallOpts, transactionId, relayer) +// Transact invokes the (paid) contract method with params as input values. +func (_EnumerableSet *EnumerableSetTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _EnumerableSet.Contract.contract.Transact(opts, method, params...) } -// CanClaim is a free data retrieval call binding the contract method 0xaa9641ab. -// -// Solidity: function canClaim(bytes32 transactionId, address relayer) view returns(bool) -func (_FastBridge *FastBridgeCallerSession) CanClaim(transactionId [32]byte, relayer common.Address) (bool, error) { - return _FastBridge.Contract.CanClaim(&_FastBridge.CallOpts, transactionId, relayer) +// FastBridgeMetaData contains all meta data concerning the FastBridge contract. +var FastBridgeMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineNotExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineTooShort\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputePeriodNotPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputePeriodPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MsgValueIncorrect\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SenderIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StatusIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenNotContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransactionRelayed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositRefunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"BridgeProofDisputed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"transactionHash\",\"type\":\"bytes32\"}],\"name\":\"BridgeProofProvided\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"BridgeRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"}],\"name\":\"BridgeRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DISPUTE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_DEADLINE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REFUNDER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REFUND_DELAY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"structIFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"bridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeProofs\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"timestamp\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeRelays\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeStatuses\",\"outputs\":[{\"internalType\":\"enumFastBridge.BridgeStatus\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"canClaim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"dispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"getBridgeTransaction\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originSender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destRecipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originFeeAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"internalType\":\"structIFastBridge.BridgeTransaction\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"destTxHash\",\"type\":\"bytes32\"}],\"name\":\"prove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"refund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "a217fddf": "DEFAULT_ADMIN_ROLE()", + "a5bbe22b": "DISPUTE_PERIOD()", + "bf333f2c": "FEE_BPS()", + "0f5f6ed7": "FEE_RATE_MAX()", + "ccc57490": "GOVERNOR_ROLE()", + "03ed0ee5": "GUARD_ROLE()", + "820688d5": "MIN_DEADLINE_PERIOD()", + "5960ccf2": "REFUNDER_ROLE()", + "190da595": "REFUND_DELAY()", + "926d7d7f": "RELAYER_ROLE()", + "45851694": "bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))", + "91ad5039": "bridgeProofs(bytes32)", + "8379a24f": "bridgeRelays(bytes32)", + "051287bc": "bridgeStatuses(bytes32)", + "aa9641ab": "canClaim(bytes32,address)", + "e00a83e0": "chainGasAmount()", + "41fcb612": "claim(bytes,address)", + "a3ec191a": "deployBlock()", + "add98c70": "dispute(bytes32)", + "ac11fb1a": "getBridgeTransaction(bytes)", + "248a9ca3": "getRoleAdmin(bytes32)", + "9010d07c": "getRoleMember(bytes32,uint256)", + "ca15c873": "getRoleMemberCount(bytes32)", + "2f2ff15d": "grantRole(bytes32,address)", + "91d14854": "hasRole(bytes32,address)", + "affed0e0": "nonce()", + "58f85880": "protocolFeeRate()", + "dcf844a7": "protocolFees(address)", + "886d36ff": "prove(bytes,bytes32)", + "5eb7d946": "refund(bytes)", + "8f0d6f17": "relay(bytes)", + "36568abe": "renounceRole(bytes32,address)", + "d547741f": "revokeRole(bytes32,address)", + "b250fe6b": "setChainGasAmount(uint256)", + "b13aa2d6": "setProtocolFeeRate(uint256)", + "01ffc9a7": "supportsInterface(bytes4)", + "06f333f2": "sweepProtocolFees(address,address)", + }, + Bin: "0x60a06040523480156200001157600080fd5b5060405162002d7a38038062002d7a833981016040819052620000349162000194565b80620000426000826200004f565b50504360805250620001bf565b6000806200005e84846200008c565b90508015620000835760008481526001602052604090206200008190846200013a565b505b90505b92915050565b6000828152602081815260408083206001600160a01b038516845290915281205460ff1662000131576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620000e83390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600162000086565b50600062000086565b600062000083836001600160a01b0384166000818152600183016020526040812054620001315750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000086565b600060208284031215620001a757600080fd5b81516001600160a01b03811681146200008357600080fd5b608051612b9f620001db60003960006106510152612b9f6000f3fe60806040526004361061026a5760003560e01c80639010d07c11610153578063add98c70116100cb578063ca15c8731161007f578063d547741f11610064578063d547741f146107a1578063dcf844a7146107c1578063e00a83e0146107ee57600080fd5b8063ca15c8731461074d578063ccc574901461076d57600080fd5b8063b13aa2d6116100b0578063b13aa2d6146106f6578063b250fe6b14610716578063bf333f2c1461073657600080fd5b8063add98c70146106c0578063affed0e0146106e057600080fd5b8063a217fddf11610122578063a5bbe22b11610107578063a5bbe22b1461047f578063aa9641ab14610673578063ac11fb1a1461069357600080fd5b8063a217fddf1461062a578063a3ec191a1461063f57600080fd5b80639010d07c146104f857806391ad50391461053057806391d14854146105b2578063926d7d7f146105f657600080fd5b806341fcb612116101e65780635eb7d946116101b55780638379a24f1161019a5780638379a24f14610495578063886d36ff146104c55780638f0d6f17146104e557600080fd5b80635eb7d9461461045f578063820688d51461047f57600080fd5b806341fcb612146103e2578063458516941461040257806358f85880146104155780635960ccf21461042b57600080fd5b80630f5f6ed71161023d578063248a9ca311610222578063248a9ca3146103725780632f2ff15d146103a257806336568abe146103c257600080fd5b80630f5f6ed714610345578063190da5951461035b57600080fd5b806301ffc9a71461026f57806303ed0ee5146102a4578063051287bc146102e657806306f333f214610323575b600080fd5b34801561027b57600080fd5b5061028f61028a3660046122fc565b610804565b60405190151581526020015b60405180910390f35b3480156102b057600080fd5b506102d87f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b60405190815260200161029b565b3480156102f257600080fd5b5061031661030136600461233e565b60056020526000908152604090205460ff1681565b60405161029b9190612386565b34801561032f57600080fd5b5061034361033e3660046123ec565b610860565b005b34801561035157600080fd5b506102d861271081565b34801561036757600080fd5b506102d862093a8081565b34801561037e57600080fd5b506102d861038d36600461233e565b60009081526020819052604090206001015490565b3480156103ae57600080fd5b506103436103bd366004612425565b610927565b3480156103ce57600080fd5b506103436103dd366004612425565b610952565b3480156103ee57600080fd5b506103436103fd366004612572565b61099e565b6103436104103660046125ef565b610bd7565b34801561042157600080fd5b506102d860025481565b34801561043757600080fd5b506102d87fdb9556138406326f00296e13ea2ad7db24ba82381212d816b1a40c23b466b32781565b34801561046b57600080fd5b5061034361047a366004612692565b610ee5565b34801561048b57600080fd5b506102d861070881565b3480156104a157600080fd5b5061028f6104b036600461233e565b60076020526000908152604090205460ff1681565b3480156104d157600080fd5b506103436104e03660046126cf565b6110bd565b6103436104f3366004612692565b6111f0565b34801561050457600080fd5b50610518610513366004612714565b611437565b6040516001600160a01b03909116815260200161029b565b34801561053c57600080fd5b5061058661054b36600461233e565b6006602052600090815260409020546bffffffffffffffffffffffff8116906c0100000000000000000000000090046001600160a01b031682565b604080516bffffffffffffffffffffffff90931683526001600160a01b0390911660208301520161029b565b3480156105be57600080fd5b5061028f6105cd366004612425565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561060257600080fd5b506102d87fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b34801561063657600080fd5b506102d8600081565b34801561064b57600080fd5b506102d87f000000000000000000000000000000000000000000000000000000000000000081565b34801561067f57600080fd5b5061028f61068e366004612425565b611456565b34801561069f57600080fd5b506106b36106ae366004612692565b611559565b60405161029b9190612736565b3480156106cc57600080fd5b506103436106db36600461233e565b6115cc565b3480156106ec57600080fd5b506102d860085481565b34801561070257600080fd5b5061034361071136600461233e565b611735565b34801561072257600080fd5b5061034361073136600461233e565b611817565b34801561074257600080fd5b506102d8620f424081565b34801561075957600080fd5b506102d861076836600461233e565b61187f565b34801561077957600080fd5b506102d87f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b3480156107ad57600080fd5b506103436107bc366004612425565b611896565b3480156107cd57600080fd5b506102d86107dc36600461281c565b60036020526000908152604090205481565b3480156107fa57600080fd5b506102d860045481565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f00000000000000000000000000000000000000000000000000000000148061085a575061085a826118bb565b92915050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561088a81611952565b6001600160a01b038316600090815260036020526040812054908190036108b15750505050565b6001600160a01b0384166000818152600360205260408120556108d590848361195f565b604080516001600160a01b038087168252851660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b505050565b60008281526020819052604090206001015461094281611952565b61094c8383611a82565b50505050565b6001600160a01b0381163314610994576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109228282611ab7565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc46109c881611952565b8251602084012060006109da85611559565b9050600260008381526005602052604090205460ff166004811115610a0157610a01612357565b14610a38576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660209081526040918290208251808401909352546bffffffffffffffffffffffff811683526c0100000000000000000000000090046001600160a01b03169082018190523314610abb576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611610b08576040517f1992d0bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600560205260409020805460ff1916600317905561010082015115610b645761010082015160808301516001600160a01b031660009081526003602052604081208054909190610b5e908490612868565b90915550505b608082015160c0830151610b826001600160a01b038316888361195f565b604080516001600160a01b03848116825260208201849052891691339188917f582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac67891015b60405180910390a45050505050505050565b46816000015163ffffffff1603610c1a576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a08101511580610c2d575060c0810151155b15610c64576040517fe38820c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608101516001600160a01b03161580610c89575060808101516001600160a01b0316155b15610cc0576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ccc61070842612868565b8161010001511015610d0a576040517f04b7fcc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d1f3083606001518460a00151611ae4565b90506000806002541115610d4c57620f424060025483610d3f919061287b565b610d499190612892565b90505b610d5681836128cd565b915060006040518061018001604052804663ffffffff168152602001856000015163ffffffff16815260200185602001516001600160a01b0316815260200185604001516001600160a01b0316815260200185606001516001600160a01b0316815260200185608001516001600160a01b031681526020018481526020018560c0015181526020018381526020018560e0015115158152602001856101000151815260200160086000815480929190610e0e906128e0565b909155509052604051610e249190602001612736565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152828252805160208083019190912060008181526005835293909320805460ff191660011790558701518751606089015160808a015160c08b015160e08c015195985095966001600160a01b039094169587957f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a95610ed6958b959094909390928e9261293c565b60405180910390a35050505050565b805160208201206000610ef783611559565b3360009081527fd2043bf65931af3dbecf60d0db8f40e4160406d7beb00522f4200cf4944a1eb8602052604090205490915060ff1615610f74578061014001514211610f6f576040517fe15ff9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fc0565b62093a80816101400151610f889190612868565b4211610fc0576040517fe15ff9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008381526005602052604090205460ff166004811115610fe557610fe5612357565b1461101c576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260056020526040808220805460ff19166004179055820151608083015161010084015160c0850151929391926110579190612868565b905061106d6001600160a01b038316848361195f565b604080516001600160a01b0384811682526020820184905285169187917fb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958910160405180910390a3505050505050565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc46110e781611952565b82516020840120600160008281526005602052604090205460ff16600481111561111357611113612357565b1461114a576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526005602090815260408083208054600260ff19909116179055805180820182526bffffffffffffffffffffffff4281168252338285018181528787526006865295849020925195516001600160a01b03166c0100000000000000000000000002959091169490941790555185815283917f4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4910160405180910390a350505050565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc461121a81611952565b81516020830120600061122c84611559565b90504663ffffffff16816020015163ffffffff1614611277576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8061014001514211156112b6576040517f559895a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526007602052604090205460ff16156112ff576040517fbef7bb7d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600760205260409020805460ff19166001179055606081015160a082015160e083015160045461012085015161134857506000611342848484611ae4565b506113b9565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b0384160161138c5761134284846113878486612868565b611ae4565b611397848484611ae4565b506113b78473eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee83611ae4565b505b845160808087015160a08089015160c0808b015160e08c01516040805163ffffffff90991689526001600160a01b0396871660208a0152938616938801939093526060870152938501528301849052861691339189917ff8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c9101610bc5565b600082815260016020526040812061144f9083611cb3565b9392505050565b6000600260008481526005602052604090205460ff16600481111561147d5761147d612357565b146114b4576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600660209081526040918290208251808401909352546bffffffffffffffffffffffff811683526001600160a01b036c01000000000000000000000000909104811691830182905284161461153a576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611949350505050565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201528251909161085a91840181019084016129ed565b7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d6115f681611952565b600260008381526005602052604090205460ff16600481111561161b5761161b612357565b14611652576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660209081526040918290208251808401909352546bffffffffffffffffffffffff8082168085526c010000000000000000000000009092046001600160a01b031693909201929092526107089142031611156116e1576040517f3e908aac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040808320805460ff19166001179055600690915280822082905551339184917f0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad49190a35050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561175f81611952565b6127108211156117d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064015b60405180910390fd5b600280549083905560408051828152602081018590527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a1505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561184181611952565b600480549083905560408051828152602081018590527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa910161180a565b600081815260016020526040812061085a90611cbf565b6000828152602081905260409020600101546118b181611952565b61094c8383611ab7565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061085a57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461085a565b61195c8133611cc9565b50565b306001600160a01b0383160361197457505050565b8060000361198157505050565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03841601611a6e576000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146119fe576040519150601f19603f3d011682016040523d82523d6000602084013e611a03565b606091505b505090508061094c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c65640000000000000000000000000060448201526064016117c7565b6109226001600160a01b0384168383611d39565b600080611a8f8484611dad565b9050801561144f576000848152600160205260409020611aaf9084611e57565b509392505050565b600080611ac48484611e6c565b9050801561144f576000848152600160205260409020611aaf9084611eef565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611c4d57611b1c836001600160a01b0316611f04565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528416906370a0823190602401602060405180830381865afa158015611b7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9f9190612ab9565b9050611bb66001600160a01b038416338685611faa565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528291908516906370a0823190602401602060405180830381865afa158015611c18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c3c9190612ab9565b611c4691906128cd565b905061144f565b348214611c86576040517f81de0bf300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0384163014611caa57611caa6001600160a01b038416858461195f565b50349392505050565b600061144f8383611fe3565b600061085a825490565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16611d35576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602481018390526044016117c7565b5050565b6040516001600160a01b0383811660248301526044820183905261092291859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061200d565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16611e4f576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055611e073390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161085a565b50600061085a565b600061144f836001600160a01b038416612089565b6000828152602081815260408083206001600160a01b038516845290915281205460ff1615611e4f576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161085a565b600061144f836001600160a01b0384166120d0565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03821601611f66576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03163b60000361195c576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b03848116602483015283811660448301526064820183905261094c9186918216906323b872dd90608401611d66565b6000826000018281548110611ffa57611ffa612ad2565b9060005260206000200154905092915050565b60006120226001600160a01b038416836121c3565b905080516000141580156120475750808060200190518101906120459190612b01565b155b15610922576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024016117c7565b6000818152600183016020526040812054611e4f5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561085a565b600081815260018301602052604081205480156121b95760006120f46001836128cd565b8554909150600090612108906001906128cd565b905080821461216d57600086600001828154811061212857612128612ad2565b906000526020600020015490508087600001848154811061214b5761214b612ad2565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061217e5761217e612b1e565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061085a565b600091505061085a565b606061144f8383600084600080856001600160a01b031684866040516121e99190612b4d565b60006040518083038185875af1925050503d8060008114612226576040519150601f19603f3d011682016040523d82523d6000602084013e61222b565b606091505b509150915061223b868383612245565b9695505050505050565b60608261225a57612255826122ba565b61144f565b815115801561227157506001600160a01b0384163b155b156122b3576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016117c7565b508061144f565b8051156122ca5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561230e57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461144f57600080fd5b60006020828403121561235057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600583106123c1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6001600160a01b038116811461195c57600080fd5b80356123e7816123c7565b919050565b600080604083850312156123ff57600080fd5b823561240a816123c7565b9150602083013561241a816123c7565b809150509250929050565b6000806040838503121561243857600080fd5b82359150602083013561241a816123c7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171561249d5761249d61244a565b60405290565b604051610180810167ffffffffffffffff8111828210171561249d5761249d61244a565b600082601f8301126124d857600080fd5b813567ffffffffffffffff808211156124f3576124f361244a565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156125395761253961244a565b8160405283815286602085880101111561255257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806040838503121561258557600080fd5b823567ffffffffffffffff81111561259c57600080fd5b6125a8858286016124c7565b925050602083013561241a816123c7565b63ffffffff8116811461195c57600080fd5b80356123e7816125b9565b801515811461195c57600080fd5b80356123e7816125d6565b6000610120828403121561260257600080fd5b61260a612479565b612613836125cb565b8152612621602084016123dc565b6020820152612632604084016123dc565b6040820152612643606084016123dc565b6060820152612654608084016123dc565b608082015260a083013560a082015260c083013560c082015261267960e084016125e4565b60e0820152610100928301359281019290925250919050565b6000602082840312156126a457600080fd5b813567ffffffffffffffff8111156126bb57600080fd5b6126c7848285016124c7565b949350505050565b600080604083850312156126e257600080fd5b823567ffffffffffffffff8111156126f957600080fd5b612705858286016124c7565b95602094909401359450505050565b6000806040838503121561272757600080fd5b50508035926020909101359150565b815163ffffffff1681526101808101602083015161275c602084018263ffffffff169052565b50604083015161277760408401826001600160a01b03169052565b50606083015161279260608401826001600160a01b03169052565b5060808301516127ad60808401826001600160a01b03169052565b5060a08301516127c860a08401826001600160a01b03169052565b5060c083015160c083015260e083015160e0830152610100808401518184015250610120808401516127fd8285018215159052565b5050610140838101519083015261016092830151929091019190915290565b60006020828403121561282e57600080fd5b813561144f816123c7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561085a5761085a612839565b808202811582820484141761085a5761085a612839565b6000826128c8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561085a5761085a612839565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361291157612911612839565b5060010190565b60005b8381101561293357818101518382015260200161291b565b50506000910152565b60e08152600088518060e084015261010061295d8282860160208e01612918565b63ffffffff9990991660208401526001600160a01b039788166040840152959096166060820152608081019390935260a0830191909152151560c0820152601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190910192915050565b80516123e7816125b9565b80516123e7816123c7565b80516123e7816125d6565b60006101808284031215612a0057600080fd5b612a086124a3565b612a11836129cc565b8152612a1f602084016129cc565b6020820152612a30604084016129d7565b6040820152612a41606084016129d7565b6060820152612a52608084016129d7565b6080820152612a6360a084016129d7565b60a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120612a968185016129e2565b908201526101408381015190820152610160928301519281019290925250919050565b600060208284031215612acb57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215612b1357600080fd5b815161144f816125d6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612b5f818460208701612918565b919091019291505056fea26469706673582212203bd946d03327296505c829a4894b0a06df193475064ebb0445d9c80a5699ab3164736f6c63430008140033", } -// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. -// -// Solidity: function chainGasAmount() view returns(uint256) -func (_FastBridge *FastBridgeCaller) ChainGasAmount(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "chainGasAmount") +// FastBridgeABI is the input ABI used to generate the binding from. +// Deprecated: Use FastBridgeMetaData.ABI instead. +var FastBridgeABI = FastBridgeMetaData.ABI - if err != nil { - return *new(*big.Int), err - } +// Deprecated: Use FastBridgeMetaData.Sigs instead. +// FastBridgeFuncSigs maps the 4-byte function signature to its string representation. +var FastBridgeFuncSigs = FastBridgeMetaData.Sigs - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) +// FastBridgeBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use FastBridgeMetaData.Bin instead. +var FastBridgeBin = FastBridgeMetaData.Bin - return out0, err +// DeployFastBridge deploys a new Ethereum contract, binding an instance of FastBridge to it. +func DeployFastBridge(auth *bind.TransactOpts, backend bind.ContractBackend, _owner common.Address) (common.Address, *types.Transaction, *FastBridge, error) { + parsed, err := FastBridgeMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(FastBridgeBin), backend, _owner) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &FastBridge{FastBridgeCaller: FastBridgeCaller{contract: contract}, FastBridgeTransactor: FastBridgeTransactor{contract: contract}, FastBridgeFilterer: FastBridgeFilterer{contract: contract}}, nil } -// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. -// -// Solidity: function chainGasAmount() view returns(uint256) -func (_FastBridge *FastBridgeSession) ChainGasAmount() (*big.Int, error) { - return _FastBridge.Contract.ChainGasAmount(&_FastBridge.CallOpts) +// FastBridge is an auto generated Go binding around an Ethereum contract. +type FastBridge struct { + FastBridgeCaller // Read-only binding to the contract + FastBridgeTransactor // Write-only binding to the contract + FastBridgeFilterer // Log filterer for contract events } -// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. -// -// Solidity: function chainGasAmount() view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) ChainGasAmount() (*big.Int, error) { - return _FastBridge.Contract.ChainGasAmount(&_FastBridge.CallOpts) +// FastBridgeCaller is an auto generated read-only Go binding around an Ethereum contract. +type FastBridgeCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// DeployBlock is a free data retrieval call binding the contract method 0xa3ec191a. -// -// Solidity: function deployBlock() view returns(uint256) -func (_FastBridge *FastBridgeCaller) DeployBlock(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "deployBlock") +// FastBridgeTransactor is an auto generated write-only Go binding around an Ethereum contract. +type FastBridgeTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} - if err != nil { - return *new(*big.Int), err - } +// FastBridgeFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type FastBridgeFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) +// FastBridgeSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type FastBridgeSession struct { + Contract *FastBridge // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} - return out0, err +// FastBridgeCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type FastBridgeCallerSession struct { + Contract *FastBridgeCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} +// FastBridgeTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type FastBridgeTransactorSession struct { + Contract *FastBridgeTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// DeployBlock is a free data retrieval call binding the contract method 0xa3ec191a. -// -// Solidity: function deployBlock() view returns(uint256) -func (_FastBridge *FastBridgeSession) DeployBlock() (*big.Int, error) { - return _FastBridge.Contract.DeployBlock(&_FastBridge.CallOpts) +// FastBridgeRaw is an auto generated low-level Go binding around an Ethereum contract. +type FastBridgeRaw struct { + Contract *FastBridge // Generic contract binding to access the raw methods on } -// DeployBlock is a free data retrieval call binding the contract method 0xa3ec191a. -// -// Solidity: function deployBlock() view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) DeployBlock() (*big.Int, error) { - return _FastBridge.Contract.DeployBlock(&_FastBridge.CallOpts) +// FastBridgeCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type FastBridgeCallerRaw struct { + Contract *FastBridgeCaller // Generic read-only contract binding to access the raw methods on } -// GetBridgeTransaction is a free data retrieval call binding the contract method 0xac11fb1a. -// -// Solidity: function getBridgeTransaction(bytes request) pure returns((uint32,uint32,address,address,address,address,uint256,uint256,uint256,bool,uint256,uint256)) -func (_FastBridge *FastBridgeCaller) GetBridgeTransaction(opts *bind.CallOpts, request []byte) (IFastBridgeBridgeTransaction, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "getBridgeTransaction", request) +// FastBridgeTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type FastBridgeTransactorRaw struct { + Contract *FastBridgeTransactor // Generic write-only contract binding to access the raw methods on +} +// NewFastBridge creates a new instance of FastBridge, bound to a specific deployed contract. +func NewFastBridge(address common.Address, backend bind.ContractBackend) (*FastBridge, error) { + contract, err := bindFastBridge(address, backend, backend, backend) if err != nil { - return *new(IFastBridgeBridgeTransaction), err + return nil, err } - - out0 := *abi.ConvertType(out[0], new(IFastBridgeBridgeTransaction)).(*IFastBridgeBridgeTransaction) - - return out0, err - + return &FastBridge{FastBridgeCaller: FastBridgeCaller{contract: contract}, FastBridgeTransactor: FastBridgeTransactor{contract: contract}, FastBridgeFilterer: FastBridgeFilterer{contract: contract}}, nil } -// GetBridgeTransaction is a free data retrieval call binding the contract method 0xac11fb1a. -// -// Solidity: function getBridgeTransaction(bytes request) pure returns((uint32,uint32,address,address,address,address,uint256,uint256,uint256,bool,uint256,uint256)) -func (_FastBridge *FastBridgeSession) GetBridgeTransaction(request []byte) (IFastBridgeBridgeTransaction, error) { - return _FastBridge.Contract.GetBridgeTransaction(&_FastBridge.CallOpts, request) +// NewFastBridgeCaller creates a new read-only instance of FastBridge, bound to a specific deployed contract. +func NewFastBridgeCaller(address common.Address, caller bind.ContractCaller) (*FastBridgeCaller, error) { + contract, err := bindFastBridge(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &FastBridgeCaller{contract: contract}, nil } -// GetBridgeTransaction is a free data retrieval call binding the contract method 0xac11fb1a. -// -// Solidity: function getBridgeTransaction(bytes request) pure returns((uint32,uint32,address,address,address,address,uint256,uint256,uint256,bool,uint256,uint256)) -func (_FastBridge *FastBridgeCallerSession) GetBridgeTransaction(request []byte) (IFastBridgeBridgeTransaction, error) { - return _FastBridge.Contract.GetBridgeTransaction(&_FastBridge.CallOpts, request) +// NewFastBridgeTransactor creates a new write-only instance of FastBridge, bound to a specific deployed contract. +func NewFastBridgeTransactor(address common.Address, transactor bind.ContractTransactor) (*FastBridgeTransactor, error) { + contract, err := bindFastBridge(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &FastBridgeTransactor{contract: contract}, nil } -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_FastBridge *FastBridgeCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { - var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "getRoleAdmin", role) - +// NewFastBridgeFilterer creates a new log filterer instance of FastBridge, bound to a specific deployed contract. +func NewFastBridgeFilterer(address common.Address, filterer bind.ContractFilterer) (*FastBridgeFilterer, error) { + contract, err := bindFastBridge(address, nil, nil, filterer) if err != nil { - return *new([32]byte), err + return nil, err } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - + return &FastBridgeFilterer{contract: contract}, nil } -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_FastBridge *FastBridgeSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { - return _FastBridge.Contract.GetRoleAdmin(&_FastBridge.CallOpts, role) +// bindFastBridge binds a generic wrapper to an already deployed contract. +func bindFastBridge(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := FastBridgeMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_FastBridge *FastBridgeCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { - return _FastBridge.Contract.GetRoleAdmin(&_FastBridge.CallOpts, role) +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_FastBridge *FastBridgeRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _FastBridge.Contract.FastBridgeCaller.contract.Call(opts, result, method, params...) } -// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_FastBridge *FastBridgeRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _FastBridge.Contract.FastBridgeTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_FastBridge *FastBridgeRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _FastBridge.Contract.FastBridgeTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_FastBridge *FastBridgeCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _FastBridge.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_FastBridge *FastBridgeTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _FastBridge.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_FastBridge *FastBridgeTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _FastBridge.Contract.contract.Transact(opts, method, params...) +} + +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. // -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_FastBridge *FastBridgeCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "hasRole", role, account) + err := _FastBridge.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") if err != nil { - return *new(bool), err + return *new([32]byte), err } - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) return out0, err } -// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. // -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_FastBridge *FastBridgeSession) HasRole(role [32]byte, account common.Address) (bool, error) { - return _FastBridge.Contract.HasRole(&_FastBridge.CallOpts, role, account) +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeSession) DEFAULTADMINROLE() ([32]byte, error) { + return _FastBridge.Contract.DEFAULTADMINROLE(&_FastBridge.CallOpts) } -// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. // -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_FastBridge *FastBridgeCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { - return _FastBridge.Contract.HasRole(&_FastBridge.CallOpts, role, account) +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCallerSession) DEFAULTADMINROLE() ([32]byte, error) { + return _FastBridge.Contract.DEFAULTADMINROLE(&_FastBridge.CallOpts) } -// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. +// DISPUTEPERIOD is a free data retrieval call binding the contract method 0xa5bbe22b. // -// Solidity: function nonce() view returns(uint256) -func (_FastBridge *FastBridgeCaller) Nonce(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function DISPUTE_PERIOD() view returns(uint256) +func (_FastBridge *FastBridgeCaller) DISPUTEPERIOD(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "nonce") + err := _FastBridge.contract.Call(opts, &out, "DISPUTE_PERIOD") if err != nil { return *new(*big.Int), err @@ -4739,26 +4429,26 @@ func (_FastBridge *FastBridgeCaller) Nonce(opts *bind.CallOpts) (*big.Int, error } -// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. +// DISPUTEPERIOD is a free data retrieval call binding the contract method 0xa5bbe22b. // -// Solidity: function nonce() view returns(uint256) -func (_FastBridge *FastBridgeSession) Nonce() (*big.Int, error) { - return _FastBridge.Contract.Nonce(&_FastBridge.CallOpts) +// Solidity: function DISPUTE_PERIOD() view returns(uint256) +func (_FastBridge *FastBridgeSession) DISPUTEPERIOD() (*big.Int, error) { + return _FastBridge.Contract.DISPUTEPERIOD(&_FastBridge.CallOpts) } -// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. +// DISPUTEPERIOD is a free data retrieval call binding the contract method 0xa5bbe22b. // -// Solidity: function nonce() view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) Nonce() (*big.Int, error) { - return _FastBridge.Contract.Nonce(&_FastBridge.CallOpts) +// Solidity: function DISPUTE_PERIOD() view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) DISPUTEPERIOD() (*big.Int, error) { + return _FastBridge.Contract.DISPUTEPERIOD(&_FastBridge.CallOpts) } -// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. // -// Solidity: function protocolFeeRate() view returns(uint256) -func (_FastBridge *FastBridgeCaller) ProtocolFeeRate(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function FEE_BPS() view returns(uint256) +func (_FastBridge *FastBridgeCaller) FEEBPS(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "protocolFeeRate") + err := _FastBridge.contract.Call(opts, &out, "FEE_BPS") if err != nil { return *new(*big.Int), err @@ -4770,26 +4460,26 @@ func (_FastBridge *FastBridgeCaller) ProtocolFeeRate(opts *bind.CallOpts) (*big. } -// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. // -// Solidity: function protocolFeeRate() view returns(uint256) -func (_FastBridge *FastBridgeSession) ProtocolFeeRate() (*big.Int, error) { - return _FastBridge.Contract.ProtocolFeeRate(&_FastBridge.CallOpts) +// Solidity: function FEE_BPS() view returns(uint256) +func (_FastBridge *FastBridgeSession) FEEBPS() (*big.Int, error) { + return _FastBridge.Contract.FEEBPS(&_FastBridge.CallOpts) } -// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. // -// Solidity: function protocolFeeRate() view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) ProtocolFeeRate() (*big.Int, error) { - return _FastBridge.Contract.ProtocolFeeRate(&_FastBridge.CallOpts) +// Solidity: function FEE_BPS() view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) FEEBPS() (*big.Int, error) { + return _FastBridge.Contract.FEEBPS(&_FastBridge.CallOpts) } -// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. +// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. // -// Solidity: function protocolFees(address ) view returns(uint256) -func (_FastBridge *FastBridgeCaller) ProtocolFees(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { +// Solidity: function FEE_RATE_MAX() view returns(uint256) +func (_FastBridge *FastBridgeCaller) FEERATEMAX(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "protocolFees", arg0) + err := _FastBridge.contract.Call(opts, &out, "FEE_RATE_MAX") if err != nil { return *new(*big.Int), err @@ -4801,751 +4491,940 @@ func (_FastBridge *FastBridgeCaller) ProtocolFees(opts *bind.CallOpts, arg0 comm } -// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. +// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. // -// Solidity: function protocolFees(address ) view returns(uint256) -func (_FastBridge *FastBridgeSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { - return _FastBridge.Contract.ProtocolFees(&_FastBridge.CallOpts, arg0) +// Solidity: function FEE_RATE_MAX() view returns(uint256) +func (_FastBridge *FastBridgeSession) FEERATEMAX() (*big.Int, error) { + return _FastBridge.Contract.FEERATEMAX(&_FastBridge.CallOpts) } -// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. +// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. // -// Solidity: function protocolFees(address ) view returns(uint256) -func (_FastBridge *FastBridgeCallerSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { - return _FastBridge.Contract.ProtocolFees(&_FastBridge.CallOpts, arg0) +// Solidity: function FEE_RATE_MAX() view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) FEERATEMAX() (*big.Int, error) { + return _FastBridge.Contract.FEERATEMAX(&_FastBridge.CallOpts) } -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. // -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_FastBridge *FastBridgeCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { +// Solidity: function GOVERNOR_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCaller) GOVERNORROLE(opts *bind.CallOpts) ([32]byte, error) { var out []interface{} - err := _FastBridge.contract.Call(opts, &out, "supportsInterface", interfaceId) + err := _FastBridge.contract.Call(opts, &out, "GOVERNOR_ROLE") if err != nil { - return *new(bool), err + return *new([32]byte), err } - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) return out0, err } -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. // -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_FastBridge *FastBridgeSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _FastBridge.Contract.SupportsInterface(&_FastBridge.CallOpts, interfaceId) +// Solidity: function GOVERNOR_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeSession) GOVERNORROLE() ([32]byte, error) { + return _FastBridge.Contract.GOVERNORROLE(&_FastBridge.CallOpts) } -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. // -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_FastBridge *FastBridgeCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _FastBridge.Contract.SupportsInterface(&_FastBridge.CallOpts, interfaceId) +// Solidity: function GOVERNOR_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCallerSession) GOVERNORROLE() ([32]byte, error) { + return _FastBridge.Contract.GOVERNORROLE(&_FastBridge.CallOpts) } -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. +// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. // -// Solidity: function addGovernor(address _governor) returns() -func (_FastBridge *FastBridgeTransactor) AddGovernor(opts *bind.TransactOpts, _governor common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "addGovernor", _governor) -} +// Solidity: function GUARD_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCaller) GUARDROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "GUARD_ROLE") -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. -// -// Solidity: function addGovernor(address _governor) returns() -func (_FastBridge *FastBridgeSession) AddGovernor(_governor common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.AddGovernor(&_FastBridge.TransactOpts, _governor) -} + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. -// -// Solidity: function addGovernor(address _governor) returns() -func (_FastBridge *FastBridgeTransactorSession) AddGovernor(_governor common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.AddGovernor(&_FastBridge.TransactOpts, _governor) } -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. +// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. // -// Solidity: function addGuard(address _guard) returns() -func (_FastBridge *FastBridgeTransactor) AddGuard(opts *bind.TransactOpts, _guard common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "addGuard", _guard) +// Solidity: function GUARD_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeSession) GUARDROLE() ([32]byte, error) { + return _FastBridge.Contract.GUARDROLE(&_FastBridge.CallOpts) } -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. +// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. // -// Solidity: function addGuard(address _guard) returns() -func (_FastBridge *FastBridgeSession) AddGuard(_guard common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.AddGuard(&_FastBridge.TransactOpts, _guard) +// Solidity: function GUARD_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCallerSession) GUARDROLE() ([32]byte, error) { + return _FastBridge.Contract.GUARDROLE(&_FastBridge.CallOpts) } -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. +// MINDEADLINEPERIOD is a free data retrieval call binding the contract method 0x820688d5. // -// Solidity: function addGuard(address _guard) returns() -func (_FastBridge *FastBridgeTransactorSession) AddGuard(_guard common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.AddGuard(&_FastBridge.TransactOpts, _guard) +// Solidity: function MIN_DEADLINE_PERIOD() view returns(uint256) +func (_FastBridge *FastBridgeCaller) MINDEADLINEPERIOD(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "MIN_DEADLINE_PERIOD") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. +// MINDEADLINEPERIOD is a free data retrieval call binding the contract method 0x820688d5. // -// Solidity: function addRelayer(address _relayer) returns() -func (_FastBridge *FastBridgeTransactor) AddRelayer(opts *bind.TransactOpts, _relayer common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "addRelayer", _relayer) +// Solidity: function MIN_DEADLINE_PERIOD() view returns(uint256) +func (_FastBridge *FastBridgeSession) MINDEADLINEPERIOD() (*big.Int, error) { + return _FastBridge.Contract.MINDEADLINEPERIOD(&_FastBridge.CallOpts) } -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. +// MINDEADLINEPERIOD is a free data retrieval call binding the contract method 0x820688d5. // -// Solidity: function addRelayer(address _relayer) returns() -func (_FastBridge *FastBridgeSession) AddRelayer(_relayer common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.AddRelayer(&_FastBridge.TransactOpts, _relayer) +// Solidity: function MIN_DEADLINE_PERIOD() view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) MINDEADLINEPERIOD() (*big.Int, error) { + return _FastBridge.Contract.MINDEADLINEPERIOD(&_FastBridge.CallOpts) } -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. +// REFUNDERROLE is a free data retrieval call binding the contract method 0x5960ccf2. // -// Solidity: function addRelayer(address _relayer) returns() -func (_FastBridge *FastBridgeTransactorSession) AddRelayer(_relayer common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.AddRelayer(&_FastBridge.TransactOpts, _relayer) +// Solidity: function REFUNDER_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCaller) REFUNDERROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "REFUNDER_ROLE") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -// Bridge is a paid mutator transaction binding the contract method 0x45851694. +// REFUNDERROLE is a free data retrieval call binding the contract method 0x5960ccf2. // -// Solidity: function bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256) params) payable returns() -func (_FastBridge *FastBridgeTransactor) Bridge(opts *bind.TransactOpts, params IFastBridgeBridgeParams) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "bridge", params) +// Solidity: function REFUNDER_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeSession) REFUNDERROLE() ([32]byte, error) { + return _FastBridge.Contract.REFUNDERROLE(&_FastBridge.CallOpts) } -// Bridge is a paid mutator transaction binding the contract method 0x45851694. +// REFUNDERROLE is a free data retrieval call binding the contract method 0x5960ccf2. // -// Solidity: function bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256) params) payable returns() -func (_FastBridge *FastBridgeSession) Bridge(params IFastBridgeBridgeParams) (*types.Transaction, error) { - return _FastBridge.Contract.Bridge(&_FastBridge.TransactOpts, params) +// Solidity: function REFUNDER_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCallerSession) REFUNDERROLE() ([32]byte, error) { + return _FastBridge.Contract.REFUNDERROLE(&_FastBridge.CallOpts) } -// Bridge is a paid mutator transaction binding the contract method 0x45851694. +// REFUNDDELAY is a free data retrieval call binding the contract method 0x190da595. // -// Solidity: function bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256) params) payable returns() -func (_FastBridge *FastBridgeTransactorSession) Bridge(params IFastBridgeBridgeParams) (*types.Transaction, error) { - return _FastBridge.Contract.Bridge(&_FastBridge.TransactOpts, params) +// Solidity: function REFUND_DELAY() view returns(uint256) +func (_FastBridge *FastBridgeCaller) REFUNDDELAY(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "REFUND_DELAY") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// Claim is a paid mutator transaction binding the contract method 0x41fcb612. +// REFUNDDELAY is a free data retrieval call binding the contract method 0x190da595. // -// Solidity: function claim(bytes request, address to) returns() -func (_FastBridge *FastBridgeTransactor) Claim(opts *bind.TransactOpts, request []byte, to common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "claim", request, to) +// Solidity: function REFUND_DELAY() view returns(uint256) +func (_FastBridge *FastBridgeSession) REFUNDDELAY() (*big.Int, error) { + return _FastBridge.Contract.REFUNDDELAY(&_FastBridge.CallOpts) } -// Claim is a paid mutator transaction binding the contract method 0x41fcb612. +// REFUNDDELAY is a free data retrieval call binding the contract method 0x190da595. // -// Solidity: function claim(bytes request, address to) returns() -func (_FastBridge *FastBridgeSession) Claim(request []byte, to common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.Claim(&_FastBridge.TransactOpts, request, to) +// Solidity: function REFUND_DELAY() view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) REFUNDDELAY() (*big.Int, error) { + return _FastBridge.Contract.REFUNDDELAY(&_FastBridge.CallOpts) } -// Claim is a paid mutator transaction binding the contract method 0x41fcb612. +// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. // -// Solidity: function claim(bytes request, address to) returns() -func (_FastBridge *FastBridgeTransactorSession) Claim(request []byte, to common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.Claim(&_FastBridge.TransactOpts, request, to) -} +// Solidity: function RELAYER_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCaller) RELAYERROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "RELAYER_ROLE") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err -// Dispute is a paid mutator transaction binding the contract method 0xadd98c70. -// -// Solidity: function dispute(bytes32 transactionId) returns() -func (_FastBridge *FastBridgeTransactor) Dispute(opts *bind.TransactOpts, transactionId [32]byte) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "dispute", transactionId) } -// Dispute is a paid mutator transaction binding the contract method 0xadd98c70. +// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. // -// Solidity: function dispute(bytes32 transactionId) returns() -func (_FastBridge *FastBridgeSession) Dispute(transactionId [32]byte) (*types.Transaction, error) { - return _FastBridge.Contract.Dispute(&_FastBridge.TransactOpts, transactionId) +// Solidity: function RELAYER_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeSession) RELAYERROLE() ([32]byte, error) { + return _FastBridge.Contract.RELAYERROLE(&_FastBridge.CallOpts) } -// Dispute is a paid mutator transaction binding the contract method 0xadd98c70. +// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. // -// Solidity: function dispute(bytes32 transactionId) returns() -func (_FastBridge *FastBridgeTransactorSession) Dispute(transactionId [32]byte) (*types.Transaction, error) { - return _FastBridge.Contract.Dispute(&_FastBridge.TransactOpts, transactionId) +// Solidity: function RELAYER_ROLE() view returns(bytes32) +func (_FastBridge *FastBridgeCallerSession) RELAYERROLE() ([32]byte, error) { + return _FastBridge.Contract.RELAYERROLE(&_FastBridge.CallOpts) } -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// BridgeProofs is a free data retrieval call binding the contract method 0x91ad5039. // -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_FastBridge *FastBridgeTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "grantRole", role, account) +// Solidity: function bridgeProofs(bytes32 ) view returns(uint96 timestamp, address relayer) +func (_FastBridge *FastBridgeCaller) BridgeProofs(opts *bind.CallOpts, arg0 [32]byte) (struct { + Timestamp *big.Int + Relayer common.Address +}, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "bridgeProofs", arg0) + + outstruct := new(struct { + Timestamp *big.Int + Relayer common.Address + }) + if err != nil { + return *outstruct, err + } + + outstruct.Timestamp = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.Relayer = *abi.ConvertType(out[1], new(common.Address)).(*common.Address) + + return *outstruct, err + } -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// BridgeProofs is a free data retrieval call binding the contract method 0x91ad5039. // -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_FastBridge *FastBridgeSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.GrantRole(&_FastBridge.TransactOpts, role, account) +// Solidity: function bridgeProofs(bytes32 ) view returns(uint96 timestamp, address relayer) +func (_FastBridge *FastBridgeSession) BridgeProofs(arg0 [32]byte) (struct { + Timestamp *big.Int + Relayer common.Address +}, error) { + return _FastBridge.Contract.BridgeProofs(&_FastBridge.CallOpts, arg0) } -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// BridgeProofs is a free data retrieval call binding the contract method 0x91ad5039. // -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_FastBridge *FastBridgeTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.GrantRole(&_FastBridge.TransactOpts, role, account) +// Solidity: function bridgeProofs(bytes32 ) view returns(uint96 timestamp, address relayer) +func (_FastBridge *FastBridgeCallerSession) BridgeProofs(arg0 [32]byte) (struct { + Timestamp *big.Int + Relayer common.Address +}, error) { + return _FastBridge.Contract.BridgeProofs(&_FastBridge.CallOpts, arg0) } -// Prove is a paid mutator transaction binding the contract method 0x886d36ff. +// BridgeRelays is a free data retrieval call binding the contract method 0x8379a24f. // -// Solidity: function prove(bytes request, bytes32 destTxHash) returns() -func (_FastBridge *FastBridgeTransactor) Prove(opts *bind.TransactOpts, request []byte, destTxHash [32]byte) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "prove", request, destTxHash) +// Solidity: function bridgeRelays(bytes32 ) view returns(bool) +func (_FastBridge *FastBridgeCaller) BridgeRelays(opts *bind.CallOpts, arg0 [32]byte) (bool, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "bridgeRelays", arg0) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + } -// Prove is a paid mutator transaction binding the contract method 0x886d36ff. +// BridgeRelays is a free data retrieval call binding the contract method 0x8379a24f. // -// Solidity: function prove(bytes request, bytes32 destTxHash) returns() -func (_FastBridge *FastBridgeSession) Prove(request []byte, destTxHash [32]byte) (*types.Transaction, error) { - return _FastBridge.Contract.Prove(&_FastBridge.TransactOpts, request, destTxHash) +// Solidity: function bridgeRelays(bytes32 ) view returns(bool) +func (_FastBridge *FastBridgeSession) BridgeRelays(arg0 [32]byte) (bool, error) { + return _FastBridge.Contract.BridgeRelays(&_FastBridge.CallOpts, arg0) } -// Prove is a paid mutator transaction binding the contract method 0x886d36ff. +// BridgeRelays is a free data retrieval call binding the contract method 0x8379a24f. // -// Solidity: function prove(bytes request, bytes32 destTxHash) returns() -func (_FastBridge *FastBridgeTransactorSession) Prove(request []byte, destTxHash [32]byte) (*types.Transaction, error) { - return _FastBridge.Contract.Prove(&_FastBridge.TransactOpts, request, destTxHash) +// Solidity: function bridgeRelays(bytes32 ) view returns(bool) +func (_FastBridge *FastBridgeCallerSession) BridgeRelays(arg0 [32]byte) (bool, error) { + return _FastBridge.Contract.BridgeRelays(&_FastBridge.CallOpts, arg0) } -// Refund is a paid mutator transaction binding the contract method 0x5eb7d946. +// BridgeStatuses is a free data retrieval call binding the contract method 0x051287bc. // -// Solidity: function refund(bytes request) returns() -func (_FastBridge *FastBridgeTransactor) Refund(opts *bind.TransactOpts, request []byte) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "refund", request) +// Solidity: function bridgeStatuses(bytes32 ) view returns(uint8) +func (_FastBridge *FastBridgeCaller) BridgeStatuses(opts *bind.CallOpts, arg0 [32]byte) (uint8, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "bridgeStatuses", arg0) + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + } -// Refund is a paid mutator transaction binding the contract method 0x5eb7d946. +// BridgeStatuses is a free data retrieval call binding the contract method 0x051287bc. // -// Solidity: function refund(bytes request) returns() -func (_FastBridge *FastBridgeSession) Refund(request []byte) (*types.Transaction, error) { - return _FastBridge.Contract.Refund(&_FastBridge.TransactOpts, request) +// Solidity: function bridgeStatuses(bytes32 ) view returns(uint8) +func (_FastBridge *FastBridgeSession) BridgeStatuses(arg0 [32]byte) (uint8, error) { + return _FastBridge.Contract.BridgeStatuses(&_FastBridge.CallOpts, arg0) } -// Refund is a paid mutator transaction binding the contract method 0x5eb7d946. +// BridgeStatuses is a free data retrieval call binding the contract method 0x051287bc. // -// Solidity: function refund(bytes request) returns() -func (_FastBridge *FastBridgeTransactorSession) Refund(request []byte) (*types.Transaction, error) { - return _FastBridge.Contract.Refund(&_FastBridge.TransactOpts, request) +// Solidity: function bridgeStatuses(bytes32 ) view returns(uint8) +func (_FastBridge *FastBridgeCallerSession) BridgeStatuses(arg0 [32]byte) (uint8, error) { + return _FastBridge.Contract.BridgeStatuses(&_FastBridge.CallOpts, arg0) } -// Relay is a paid mutator transaction binding the contract method 0x8f0d6f17. +// CanClaim is a free data retrieval call binding the contract method 0xaa9641ab. // -// Solidity: function relay(bytes request) payable returns() -func (_FastBridge *FastBridgeTransactor) Relay(opts *bind.TransactOpts, request []byte) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "relay", request) +// Solidity: function canClaim(bytes32 transactionId, address relayer) view returns(bool) +func (_FastBridge *FastBridgeCaller) CanClaim(opts *bind.CallOpts, transactionId [32]byte, relayer common.Address) (bool, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "canClaim", transactionId, relayer) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + } -// Relay is a paid mutator transaction binding the contract method 0x8f0d6f17. +// CanClaim is a free data retrieval call binding the contract method 0xaa9641ab. // -// Solidity: function relay(bytes request) payable returns() -func (_FastBridge *FastBridgeSession) Relay(request []byte) (*types.Transaction, error) { - return _FastBridge.Contract.Relay(&_FastBridge.TransactOpts, request) +// Solidity: function canClaim(bytes32 transactionId, address relayer) view returns(bool) +func (_FastBridge *FastBridgeSession) CanClaim(transactionId [32]byte, relayer common.Address) (bool, error) { + return _FastBridge.Contract.CanClaim(&_FastBridge.CallOpts, transactionId, relayer) } -// Relay is a paid mutator transaction binding the contract method 0x8f0d6f17. +// CanClaim is a free data retrieval call binding the contract method 0xaa9641ab. // -// Solidity: function relay(bytes request) payable returns() -func (_FastBridge *FastBridgeTransactorSession) Relay(request []byte) (*types.Transaction, error) { - return _FastBridge.Contract.Relay(&_FastBridge.TransactOpts, request) +// Solidity: function canClaim(bytes32 transactionId, address relayer) view returns(bool) +func (_FastBridge *FastBridgeCallerSession) CanClaim(transactionId [32]byte, relayer common.Address) (bool, error) { + return _FastBridge.Contract.CanClaim(&_FastBridge.CallOpts, transactionId, relayer) } -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. +// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. // -// Solidity: function removeGovernor(address _governor) returns() -func (_FastBridge *FastBridgeTransactor) RemoveGovernor(opts *bind.TransactOpts, _governor common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "removeGovernor", _governor) +// Solidity: function chainGasAmount() view returns(uint256) +func (_FastBridge *FastBridgeCaller) ChainGasAmount(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "chainGasAmount") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. +// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. // -// Solidity: function removeGovernor(address _governor) returns() -func (_FastBridge *FastBridgeSession) RemoveGovernor(_governor common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RemoveGovernor(&_FastBridge.TransactOpts, _governor) +// Solidity: function chainGasAmount() view returns(uint256) +func (_FastBridge *FastBridgeSession) ChainGasAmount() (*big.Int, error) { + return _FastBridge.Contract.ChainGasAmount(&_FastBridge.CallOpts) } -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. +// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. // -// Solidity: function removeGovernor(address _governor) returns() -func (_FastBridge *FastBridgeTransactorSession) RemoveGovernor(_governor common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RemoveGovernor(&_FastBridge.TransactOpts, _governor) +// Solidity: function chainGasAmount() view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) ChainGasAmount() (*big.Int, error) { + return _FastBridge.Contract.ChainGasAmount(&_FastBridge.CallOpts) } -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. +// DeployBlock is a free data retrieval call binding the contract method 0xa3ec191a. // -// Solidity: function removeGuard(address _guard) returns() -func (_FastBridge *FastBridgeTransactor) RemoveGuard(opts *bind.TransactOpts, _guard common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "removeGuard", _guard) +// Solidity: function deployBlock() view returns(uint256) +func (_FastBridge *FastBridgeCaller) DeployBlock(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "deployBlock") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. +// DeployBlock is a free data retrieval call binding the contract method 0xa3ec191a. // -// Solidity: function removeGuard(address _guard) returns() -func (_FastBridge *FastBridgeSession) RemoveGuard(_guard common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RemoveGuard(&_FastBridge.TransactOpts, _guard) +// Solidity: function deployBlock() view returns(uint256) +func (_FastBridge *FastBridgeSession) DeployBlock() (*big.Int, error) { + return _FastBridge.Contract.DeployBlock(&_FastBridge.CallOpts) } -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. +// DeployBlock is a free data retrieval call binding the contract method 0xa3ec191a. // -// Solidity: function removeGuard(address _guard) returns() -func (_FastBridge *FastBridgeTransactorSession) RemoveGuard(_guard common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RemoveGuard(&_FastBridge.TransactOpts, _guard) +// Solidity: function deployBlock() view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) DeployBlock() (*big.Int, error) { + return _FastBridge.Contract.DeployBlock(&_FastBridge.CallOpts) } -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. +// GetBridgeTransaction is a free data retrieval call binding the contract method 0xac11fb1a. // -// Solidity: function removeRelayer(address _relayer) returns() -func (_FastBridge *FastBridgeTransactor) RemoveRelayer(opts *bind.TransactOpts, _relayer common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "removeRelayer", _relayer) +// Solidity: function getBridgeTransaction(bytes request) pure returns((uint32,uint32,address,address,address,address,uint256,uint256,uint256,bool,uint256,uint256)) +func (_FastBridge *FastBridgeCaller) GetBridgeTransaction(opts *bind.CallOpts, request []byte) (IFastBridgeBridgeTransaction, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "getBridgeTransaction", request) + + if err != nil { + return *new(IFastBridgeBridgeTransaction), err + } + + out0 := *abi.ConvertType(out[0], new(IFastBridgeBridgeTransaction)).(*IFastBridgeBridgeTransaction) + + return out0, err + } -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. +// GetBridgeTransaction is a free data retrieval call binding the contract method 0xac11fb1a. // -// Solidity: function removeRelayer(address _relayer) returns() -func (_FastBridge *FastBridgeSession) RemoveRelayer(_relayer common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RemoveRelayer(&_FastBridge.TransactOpts, _relayer) +// Solidity: function getBridgeTransaction(bytes request) pure returns((uint32,uint32,address,address,address,address,uint256,uint256,uint256,bool,uint256,uint256)) +func (_FastBridge *FastBridgeSession) GetBridgeTransaction(request []byte) (IFastBridgeBridgeTransaction, error) { + return _FastBridge.Contract.GetBridgeTransaction(&_FastBridge.CallOpts, request) } -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. +// GetBridgeTransaction is a free data retrieval call binding the contract method 0xac11fb1a. // -// Solidity: function removeRelayer(address _relayer) returns() -func (_FastBridge *FastBridgeTransactorSession) RemoveRelayer(_relayer common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RemoveRelayer(&_FastBridge.TransactOpts, _relayer) +// Solidity: function getBridgeTransaction(bytes request) pure returns((uint32,uint32,address,address,address,address,uint256,uint256,uint256,bool,uint256,uint256)) +func (_FastBridge *FastBridgeCallerSession) GetBridgeTransaction(request []byte) (IFastBridgeBridgeTransaction, error) { + return _FastBridge.Contract.GetBridgeTransaction(&_FastBridge.CallOpts, request) } -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. // -// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() -func (_FastBridge *FastBridgeTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "renounceRole", role, callerConfirmation) +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_FastBridge *FastBridgeCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "getRoleAdmin", role) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. // -// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() -func (_FastBridge *FastBridgeSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RenounceRole(&_FastBridge.TransactOpts, role, callerConfirmation) +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_FastBridge *FastBridgeSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _FastBridge.Contract.GetRoleAdmin(&_FastBridge.CallOpts, role) } -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. // -// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() -func (_FastBridge *FastBridgeTransactorSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RenounceRole(&_FastBridge.TransactOpts, role, callerConfirmation) +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_FastBridge *FastBridgeCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _FastBridge.Contract.GetRoleAdmin(&_FastBridge.CallOpts, role) } -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. // -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_FastBridge *FastBridgeTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "revokeRole", role, account) +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_FastBridge *FastBridgeCaller) GetRoleMember(opts *bind.CallOpts, role [32]byte, index *big.Int) (common.Address, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "getRoleMember", role, index) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + } -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. // -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_FastBridge *FastBridgeSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RevokeRole(&_FastBridge.TransactOpts, role, account) +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_FastBridge *FastBridgeSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _FastBridge.Contract.GetRoleMember(&_FastBridge.CallOpts, role, index) } -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. // -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_FastBridge *FastBridgeTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.RevokeRole(&_FastBridge.TransactOpts, role, account) +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_FastBridge *FastBridgeCallerSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _FastBridge.Contract.GetRoleMember(&_FastBridge.CallOpts, role, index) } -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. // -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_FastBridge *FastBridgeTransactor) SetChainGasAmount(opts *bind.TransactOpts, newChainGasAmount *big.Int) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "setChainGasAmount", newChainGasAmount) +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_FastBridge *FastBridgeCaller) GetRoleMemberCount(opts *bind.CallOpts, role [32]byte) (*big.Int, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "getRoleMemberCount", role) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. // -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_FastBridge *FastBridgeSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { - return _FastBridge.Contract.SetChainGasAmount(&_FastBridge.TransactOpts, newChainGasAmount) +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_FastBridge *FastBridgeSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _FastBridge.Contract.GetRoleMemberCount(&_FastBridge.CallOpts, role) } -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. // -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_FastBridge *FastBridgeTransactorSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { - return _FastBridge.Contract.SetChainGasAmount(&_FastBridge.TransactOpts, newChainGasAmount) +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _FastBridge.Contract.GetRoleMemberCount(&_FastBridge.CallOpts, role) } -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. +// HasRole is a free data retrieval call binding the contract method 0x91d14854. // -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_FastBridge *FastBridgeTransactor) SetProtocolFeeRate(opts *bind.TransactOpts, newFeeRate *big.Int) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "setProtocolFeeRate", newFeeRate) +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_FastBridge *FastBridgeCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "hasRole", role, account) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + } -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. +// HasRole is a free data retrieval call binding the contract method 0x91d14854. // -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_FastBridge *FastBridgeSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { - return _FastBridge.Contract.SetProtocolFeeRate(&_FastBridge.TransactOpts, newFeeRate) +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_FastBridge *FastBridgeSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _FastBridge.Contract.HasRole(&_FastBridge.CallOpts, role, account) } -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. +// HasRole is a free data retrieval call binding the contract method 0x91d14854. // -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_FastBridge *FastBridgeTransactorSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { - return _FastBridge.Contract.SetProtocolFeeRate(&_FastBridge.TransactOpts, newFeeRate) +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_FastBridge *FastBridgeCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _FastBridge.Contract.HasRole(&_FastBridge.CallOpts, role, account) } -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. // -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_FastBridge *FastBridgeTransactor) SweepProtocolFees(opts *bind.TransactOpts, token common.Address, recipient common.Address) (*types.Transaction, error) { - return _FastBridge.contract.Transact(opts, "sweepProtocolFees", token, recipient) +// Solidity: function nonce() view returns(uint256) +func (_FastBridge *FastBridgeCaller) Nonce(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "nonce") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. // -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_FastBridge *FastBridgeSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.SweepProtocolFees(&_FastBridge.TransactOpts, token, recipient) +// Solidity: function nonce() view returns(uint256) +func (_FastBridge *FastBridgeSession) Nonce() (*big.Int, error) { + return _FastBridge.Contract.Nonce(&_FastBridge.CallOpts) } -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. // -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_FastBridge *FastBridgeTransactorSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { - return _FastBridge.Contract.SweepProtocolFees(&_FastBridge.TransactOpts, token, recipient) +// Solidity: function nonce() view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) Nonce() (*big.Int, error) { + return _FastBridge.Contract.Nonce(&_FastBridge.CallOpts) } -// FastBridgeBridgeDepositClaimedIterator is returned from FilterBridgeDepositClaimed and is used to iterate over the raw logs and unpacked data for BridgeDepositClaimed events raised by the FastBridge contract. -type FastBridgeBridgeDepositClaimedIterator struct { - Event *FastBridgeBridgeDepositClaimed // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} +// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// +// Solidity: function protocolFeeRate() view returns(uint256) +func (_FastBridge *FastBridgeCaller) ProtocolFeeRate(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "protocolFeeRate") -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *FastBridgeBridgeDepositClaimedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false + if err != nil { + return *new(*big.Int), err } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(FastBridgeBridgeDepositClaimed) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(FastBridgeBridgeDepositClaimed) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} + return out0, err -// Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeBridgeDepositClaimedIterator) Error() error { - return it.fail } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *FastBridgeBridgeDepositClaimedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// +// Solidity: function protocolFeeRate() view returns(uint256) +func (_FastBridge *FastBridgeSession) ProtocolFeeRate() (*big.Int, error) { + return _FastBridge.Contract.ProtocolFeeRate(&_FastBridge.CallOpts) } -// FastBridgeBridgeDepositClaimed represents a BridgeDepositClaimed event raised by the FastBridge contract. -type FastBridgeBridgeDepositClaimed struct { - TransactionId [32]byte - Relayer common.Address - To common.Address - Token common.Address - Amount *big.Int - Raw types.Log // Blockchain specific contextual infos +// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// +// Solidity: function protocolFeeRate() view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) ProtocolFeeRate() (*big.Int, error) { + return _FastBridge.Contract.ProtocolFeeRate(&_FastBridge.CallOpts) } -// FilterBridgeDepositClaimed is a free log retrieval operation binding the contract event 0x582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac678. +// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. // -// Solidity: event BridgeDepositClaimed(bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount) -func (_FastBridge *FastBridgeFilterer) FilterBridgeDepositClaimed(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address, to []common.Address) (*FastBridgeBridgeDepositClaimedIterator, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } +// Solidity: function protocolFees(address ) view returns(uint256) +func (_FastBridge *FastBridgeCaller) ProtocolFees(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "protocolFees", arg0) - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeDepositClaimed", transactionIdRule, relayerRule, toRule) if err != nil { - return nil, err + return *new(*big.Int), err } - return &FastBridgeBridgeDepositClaimedIterator{contract: _FastBridge.contract, event: "BridgeDepositClaimed", logs: logs, sub: sub}, nil -} -// WatchBridgeDepositClaimed is a free log subscription operation binding the contract event 0x582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac678. -// -// Solidity: event BridgeDepositClaimed(bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount) -func (_FastBridge *FastBridgeFilterer) WatchBridgeDepositClaimed(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeDepositClaimed, transactionId [][32]byte, relayer []common.Address, to []common.Address) (event.Subscription, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeDepositClaimed", transactionIdRule, relayerRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(FastBridgeBridgeDepositClaimed) - if err := _FastBridge.contract.UnpackLog(event, "BridgeDepositClaimed", log); err != nil { - return err - } - event.Raw = log + return out0, err - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil } -// ParseBridgeDepositClaimed is a log parse operation binding the contract event 0x582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac678. +// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. // -// Solidity: event BridgeDepositClaimed(bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount) -func (_FastBridge *FastBridgeFilterer) ParseBridgeDepositClaimed(log types.Log) (*FastBridgeBridgeDepositClaimed, error) { - event := new(FastBridgeBridgeDepositClaimed) - if err := _FastBridge.contract.UnpackLog(event, "BridgeDepositClaimed", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function protocolFees(address ) view returns(uint256) +func (_FastBridge *FastBridgeSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { + return _FastBridge.Contract.ProtocolFees(&_FastBridge.CallOpts, arg0) } -// FastBridgeBridgeDepositRefundedIterator is returned from FilterBridgeDepositRefunded and is used to iterate over the raw logs and unpacked data for BridgeDepositRefunded events raised by the FastBridge contract. -type FastBridgeBridgeDepositRefundedIterator struct { - Event *FastBridgeBridgeDepositRefunded // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. +// +// Solidity: function protocolFees(address ) view returns(uint256) +func (_FastBridge *FastBridgeCallerSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { + return _FastBridge.Contract.ProtocolFees(&_FastBridge.CallOpts, arg0) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *FastBridgeBridgeDepositRefundedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(FastBridgeBridgeDepositRefunded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_FastBridge *FastBridgeCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _FastBridge.contract.Call(opts, &out, "supportsInterface", interfaceId) - default: - return false - } + if err != nil { + return *new(bool), err } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(FastBridgeBridgeDepositRefunded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err -// Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeBridgeDepositRefundedIterator) Error() error { - return it.fail } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *FastBridgeBridgeDepositRefundedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_FastBridge *FastBridgeSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _FastBridge.Contract.SupportsInterface(&_FastBridge.CallOpts, interfaceId) } -// FastBridgeBridgeDepositRefunded represents a BridgeDepositRefunded event raised by the FastBridge contract. -type FastBridgeBridgeDepositRefunded struct { - TransactionId [32]byte - To common.Address - Token common.Address - Amount *big.Int - Raw types.Log // Blockchain specific contextual infos +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_FastBridge *FastBridgeCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _FastBridge.Contract.SupportsInterface(&_FastBridge.CallOpts, interfaceId) } -// FilterBridgeDepositRefunded is a free log retrieval operation binding the contract event 0xb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958. +// Bridge is a paid mutator transaction binding the contract method 0x45851694. // -// Solidity: event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount) -func (_FastBridge *FastBridgeFilterer) FilterBridgeDepositRefunded(opts *bind.FilterOpts, transactionId [][32]byte, to []common.Address) (*FastBridgeBridgeDepositRefundedIterator, error) { +// Solidity: function bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256) params) payable returns() +func (_FastBridge *FastBridgeTransactor) Bridge(opts *bind.TransactOpts, params IFastBridgeBridgeParams) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "bridge", params) +} - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } +// Bridge is a paid mutator transaction binding the contract method 0x45851694. +// +// Solidity: function bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256) params) payable returns() +func (_FastBridge *FastBridgeSession) Bridge(params IFastBridgeBridgeParams) (*types.Transaction, error) { + return _FastBridge.Contract.Bridge(&_FastBridge.TransactOpts, params) +} - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeDepositRefunded", transactionIdRule, toRule) - if err != nil { - return nil, err - } - return &FastBridgeBridgeDepositRefundedIterator{contract: _FastBridge.contract, event: "BridgeDepositRefunded", logs: logs, sub: sub}, nil +// Bridge is a paid mutator transaction binding the contract method 0x45851694. +// +// Solidity: function bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256) params) payable returns() +func (_FastBridge *FastBridgeTransactorSession) Bridge(params IFastBridgeBridgeParams) (*types.Transaction, error) { + return _FastBridge.Contract.Bridge(&_FastBridge.TransactOpts, params) } -// WatchBridgeDepositRefunded is a free log subscription operation binding the contract event 0xb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958. +// Claim is a paid mutator transaction binding the contract method 0x41fcb612. // -// Solidity: event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount) -func (_FastBridge *FastBridgeFilterer) WatchBridgeDepositRefunded(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeDepositRefunded, transactionId [][32]byte, to []common.Address) (event.Subscription, error) { +// Solidity: function claim(bytes request, address to) returns() +func (_FastBridge *FastBridgeTransactor) Claim(opts *bind.TransactOpts, request []byte, to common.Address) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "claim", request, to) +} - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } +// Claim is a paid mutator transaction binding the contract method 0x41fcb612. +// +// Solidity: function claim(bytes request, address to) returns() +func (_FastBridge *FastBridgeSession) Claim(request []byte, to common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.Claim(&_FastBridge.TransactOpts, request, to) +} - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeDepositRefunded", transactionIdRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(FastBridgeBridgeDepositRefunded) - if err := _FastBridge.contract.UnpackLog(event, "BridgeDepositRefunded", log); err != nil { - return err - } - event.Raw = log +// Claim is a paid mutator transaction binding the contract method 0x41fcb612. +// +// Solidity: function claim(bytes request, address to) returns() +func (_FastBridge *FastBridgeTransactorSession) Claim(request []byte, to common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.Claim(&_FastBridge.TransactOpts, request, to) +} - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil +// Dispute is a paid mutator transaction binding the contract method 0xadd98c70. +// +// Solidity: function dispute(bytes32 transactionId) returns() +func (_FastBridge *FastBridgeTransactor) Dispute(opts *bind.TransactOpts, transactionId [32]byte) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "dispute", transactionId) } -// ParseBridgeDepositRefunded is a log parse operation binding the contract event 0xb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958. +// Dispute is a paid mutator transaction binding the contract method 0xadd98c70. // -// Solidity: event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount) -func (_FastBridge *FastBridgeFilterer) ParseBridgeDepositRefunded(log types.Log) (*FastBridgeBridgeDepositRefunded, error) { - event := new(FastBridgeBridgeDepositRefunded) - if err := _FastBridge.contract.UnpackLog(event, "BridgeDepositRefunded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function dispute(bytes32 transactionId) returns() +func (_FastBridge *FastBridgeSession) Dispute(transactionId [32]byte) (*types.Transaction, error) { + return _FastBridge.Contract.Dispute(&_FastBridge.TransactOpts, transactionId) } -// FastBridgeBridgeProofDisputedIterator is returned from FilterBridgeProofDisputed and is used to iterate over the raw logs and unpacked data for BridgeProofDisputed events raised by the FastBridge contract. -type FastBridgeBridgeProofDisputedIterator struct { - Event *FastBridgeBridgeProofDisputed // Event containing the contract specifics and raw log +// Dispute is a paid mutator transaction binding the contract method 0xadd98c70. +// +// Solidity: function dispute(bytes32 transactionId) returns() +func (_FastBridge *FastBridgeTransactorSession) Dispute(transactionId [32]byte) (*types.Transaction, error) { + return _FastBridge.Contract.Dispute(&_FastBridge.TransactOpts, transactionId) +} + +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_FastBridge *FastBridgeTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "grantRole", role, account) +} + +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_FastBridge *FastBridgeSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.GrantRole(&_FastBridge.TransactOpts, role, account) +} + +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_FastBridge *FastBridgeTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.GrantRole(&_FastBridge.TransactOpts, role, account) +} + +// Prove is a paid mutator transaction binding the contract method 0x886d36ff. +// +// Solidity: function prove(bytes request, bytes32 destTxHash) returns() +func (_FastBridge *FastBridgeTransactor) Prove(opts *bind.TransactOpts, request []byte, destTxHash [32]byte) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "prove", request, destTxHash) +} + +// Prove is a paid mutator transaction binding the contract method 0x886d36ff. +// +// Solidity: function prove(bytes request, bytes32 destTxHash) returns() +func (_FastBridge *FastBridgeSession) Prove(request []byte, destTxHash [32]byte) (*types.Transaction, error) { + return _FastBridge.Contract.Prove(&_FastBridge.TransactOpts, request, destTxHash) +} + +// Prove is a paid mutator transaction binding the contract method 0x886d36ff. +// +// Solidity: function prove(bytes request, bytes32 destTxHash) returns() +func (_FastBridge *FastBridgeTransactorSession) Prove(request []byte, destTxHash [32]byte) (*types.Transaction, error) { + return _FastBridge.Contract.Prove(&_FastBridge.TransactOpts, request, destTxHash) +} + +// Refund is a paid mutator transaction binding the contract method 0x5eb7d946. +// +// Solidity: function refund(bytes request) returns() +func (_FastBridge *FastBridgeTransactor) Refund(opts *bind.TransactOpts, request []byte) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "refund", request) +} + +// Refund is a paid mutator transaction binding the contract method 0x5eb7d946. +// +// Solidity: function refund(bytes request) returns() +func (_FastBridge *FastBridgeSession) Refund(request []byte) (*types.Transaction, error) { + return _FastBridge.Contract.Refund(&_FastBridge.TransactOpts, request) +} + +// Refund is a paid mutator transaction binding the contract method 0x5eb7d946. +// +// Solidity: function refund(bytes request) returns() +func (_FastBridge *FastBridgeTransactorSession) Refund(request []byte) (*types.Transaction, error) { + return _FastBridge.Contract.Refund(&_FastBridge.TransactOpts, request) +} + +// Relay is a paid mutator transaction binding the contract method 0x8f0d6f17. +// +// Solidity: function relay(bytes request) payable returns() +func (_FastBridge *FastBridgeTransactor) Relay(opts *bind.TransactOpts, request []byte) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "relay", request) +} + +// Relay is a paid mutator transaction binding the contract method 0x8f0d6f17. +// +// Solidity: function relay(bytes request) payable returns() +func (_FastBridge *FastBridgeSession) Relay(request []byte) (*types.Transaction, error) { + return _FastBridge.Contract.Relay(&_FastBridge.TransactOpts, request) +} + +// Relay is a paid mutator transaction binding the contract method 0x8f0d6f17. +// +// Solidity: function relay(bytes request) payable returns() +func (_FastBridge *FastBridgeTransactorSession) Relay(request []byte) (*types.Transaction, error) { + return _FastBridge.Contract.Relay(&_FastBridge.TransactOpts, request) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_FastBridge *FastBridgeTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "renounceRole", role, callerConfirmation) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_FastBridge *FastBridgeSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.RenounceRole(&_FastBridge.TransactOpts, role, callerConfirmation) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_FastBridge *FastBridgeTransactorSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.RenounceRole(&_FastBridge.TransactOpts, role, callerConfirmation) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_FastBridge *FastBridgeTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "revokeRole", role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_FastBridge *FastBridgeSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.RevokeRole(&_FastBridge.TransactOpts, role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_FastBridge *FastBridgeTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.RevokeRole(&_FastBridge.TransactOpts, role, account) +} + +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_FastBridge *FastBridgeTransactor) SetChainGasAmount(opts *bind.TransactOpts, newChainGasAmount *big.Int) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "setChainGasAmount", newChainGasAmount) +} + +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_FastBridge *FastBridgeSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { + return _FastBridge.Contract.SetChainGasAmount(&_FastBridge.TransactOpts, newChainGasAmount) +} + +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_FastBridge *FastBridgeTransactorSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { + return _FastBridge.Contract.SetChainGasAmount(&_FastBridge.TransactOpts, newChainGasAmount) +} + +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. +// +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_FastBridge *FastBridgeTransactor) SetProtocolFeeRate(opts *bind.TransactOpts, newFeeRate *big.Int) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "setProtocolFeeRate", newFeeRate) +} + +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. +// +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_FastBridge *FastBridgeSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { + return _FastBridge.Contract.SetProtocolFeeRate(&_FastBridge.TransactOpts, newFeeRate) +} + +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. +// +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_FastBridge *FastBridgeTransactorSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { + return _FastBridge.Contract.SetProtocolFeeRate(&_FastBridge.TransactOpts, newFeeRate) +} + +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_FastBridge *FastBridgeTransactor) SweepProtocolFees(opts *bind.TransactOpts, token common.Address, recipient common.Address) (*types.Transaction, error) { + return _FastBridge.contract.Transact(opts, "sweepProtocolFees", token, recipient) +} + +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_FastBridge *FastBridgeSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.SweepProtocolFees(&_FastBridge.TransactOpts, token, recipient) +} + +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_FastBridge *FastBridgeTransactorSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { + return _FastBridge.Contract.SweepProtocolFees(&_FastBridge.TransactOpts, token, recipient) +} + +// FastBridgeBridgeDepositClaimedIterator is returned from FilterBridgeDepositClaimed and is used to iterate over the raw logs and unpacked data for BridgeDepositClaimed events raised by the FastBridge contract. +type FastBridgeBridgeDepositClaimedIterator struct { + Event *FastBridgeBridgeDepositClaimed // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -5559,7 +5438,7 @@ type FastBridgeBridgeProofDisputedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeBridgeProofDisputedIterator) Next() bool { +func (it *FastBridgeBridgeDepositClaimedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -5568,7 +5447,7 @@ func (it *FastBridgeBridgeProofDisputedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeBridgeProofDisputed) + it.Event = new(FastBridgeBridgeDepositClaimed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -5583,7 +5462,7 @@ func (it *FastBridgeBridgeProofDisputedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeBridgeProofDisputed) + it.Event = new(FastBridgeBridgeDepositClaimed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -5599,28 +5478,31 @@ func (it *FastBridgeBridgeProofDisputedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeBridgeProofDisputedIterator) Error() error { +func (it *FastBridgeBridgeDepositClaimedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeBridgeProofDisputedIterator) Close() error { +func (it *FastBridgeBridgeDepositClaimedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeBridgeProofDisputed represents a BridgeProofDisputed event raised by the FastBridge contract. -type FastBridgeBridgeProofDisputed struct { +// FastBridgeBridgeDepositClaimed represents a BridgeDepositClaimed event raised by the FastBridge contract. +type FastBridgeBridgeDepositClaimed struct { TransactionId [32]byte Relayer common.Address + To common.Address + Token common.Address + Amount *big.Int Raw types.Log // Blockchain specific contextual infos } -// FilterBridgeProofDisputed is a free log retrieval operation binding the contract event 0x0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad4. +// FilterBridgeDepositClaimed is a free log retrieval operation binding the contract event 0x582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac678. // -// Solidity: event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer) -func (_FastBridge *FastBridgeFilterer) FilterBridgeProofDisputed(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address) (*FastBridgeBridgeProofDisputedIterator, error) { +// Solidity: event BridgeDepositClaimed(bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount) +func (_FastBridge *FastBridgeFilterer) FilterBridgeDepositClaimed(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address, to []common.Address) (*FastBridgeBridgeDepositClaimedIterator, error) { var transactionIdRule []interface{} for _, transactionIdItem := range transactionId { @@ -5630,18 +5512,22 @@ func (_FastBridge *FastBridgeFilterer) FilterBridgeProofDisputed(opts *bind.Filt for _, relayerItem := range relayer { relayerRule = append(relayerRule, relayerItem) } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeProofDisputed", transactionIdRule, relayerRule) + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeDepositClaimed", transactionIdRule, relayerRule, toRule) if err != nil { return nil, err } - return &FastBridgeBridgeProofDisputedIterator{contract: _FastBridge.contract, event: "BridgeProofDisputed", logs: logs, sub: sub}, nil + return &FastBridgeBridgeDepositClaimedIterator{contract: _FastBridge.contract, event: "BridgeDepositClaimed", logs: logs, sub: sub}, nil } -// WatchBridgeProofDisputed is a free log subscription operation binding the contract event 0x0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad4. +// WatchBridgeDepositClaimed is a free log subscription operation binding the contract event 0x582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac678. // -// Solidity: event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer) -func (_FastBridge *FastBridgeFilterer) WatchBridgeProofDisputed(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeProofDisputed, transactionId [][32]byte, relayer []common.Address) (event.Subscription, error) { +// Solidity: event BridgeDepositClaimed(bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount) +func (_FastBridge *FastBridgeFilterer) WatchBridgeDepositClaimed(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeDepositClaimed, transactionId [][32]byte, relayer []common.Address, to []common.Address) (event.Subscription, error) { var transactionIdRule []interface{} for _, transactionIdItem := range transactionId { @@ -5651,8 +5537,12 @@ func (_FastBridge *FastBridgeFilterer) WatchBridgeProofDisputed(opts *bind.Watch for _, relayerItem := range relayer { relayerRule = append(relayerRule, relayerItem) } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeProofDisputed", transactionIdRule, relayerRule) + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeDepositClaimed", transactionIdRule, relayerRule, toRule) if err != nil { return nil, err } @@ -5662,8 +5552,8 @@ func (_FastBridge *FastBridgeFilterer) WatchBridgeProofDisputed(opts *bind.Watch select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeBridgeProofDisputed) - if err := _FastBridge.contract.UnpackLog(event, "BridgeProofDisputed", log); err != nil { + event := new(FastBridgeBridgeDepositClaimed) + if err := _FastBridge.contract.UnpackLog(event, "BridgeDepositClaimed", log); err != nil { return err } event.Raw = log @@ -5684,21 +5574,21 @@ func (_FastBridge *FastBridgeFilterer) WatchBridgeProofDisputed(opts *bind.Watch }), nil } -// ParseBridgeProofDisputed is a log parse operation binding the contract event 0x0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad4. +// ParseBridgeDepositClaimed is a log parse operation binding the contract event 0x582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac678. // -// Solidity: event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer) -func (_FastBridge *FastBridgeFilterer) ParseBridgeProofDisputed(log types.Log) (*FastBridgeBridgeProofDisputed, error) { - event := new(FastBridgeBridgeProofDisputed) - if err := _FastBridge.contract.UnpackLog(event, "BridgeProofDisputed", log); err != nil { - return nil, err - } +// Solidity: event BridgeDepositClaimed(bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount) +func (_FastBridge *FastBridgeFilterer) ParseBridgeDepositClaimed(log types.Log) (*FastBridgeBridgeDepositClaimed, error) { + event := new(FastBridgeBridgeDepositClaimed) + if err := _FastBridge.contract.UnpackLog(event, "BridgeDepositClaimed", log); err != nil { + return nil, err + } event.Raw = log return event, nil } -// FastBridgeBridgeProofProvidedIterator is returned from FilterBridgeProofProvided and is used to iterate over the raw logs and unpacked data for BridgeProofProvided events raised by the FastBridge contract. -type FastBridgeBridgeProofProvidedIterator struct { - Event *FastBridgeBridgeProofProvided // Event containing the contract specifics and raw log +// FastBridgeBridgeDepositRefundedIterator is returned from FilterBridgeDepositRefunded and is used to iterate over the raw logs and unpacked data for BridgeDepositRefunded events raised by the FastBridge contract. +type FastBridgeBridgeDepositRefundedIterator struct { + Event *FastBridgeBridgeDepositRefunded // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -5712,7 +5602,7 @@ type FastBridgeBridgeProofProvidedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeBridgeProofProvidedIterator) Next() bool { +func (it *FastBridgeBridgeDepositRefundedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -5721,7 +5611,7 @@ func (it *FastBridgeBridgeProofProvidedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeBridgeProofProvided) + it.Event = new(FastBridgeBridgeDepositRefunded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -5736,7 +5626,7 @@ func (it *FastBridgeBridgeProofProvidedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeBridgeProofProvided) + it.Event = new(FastBridgeBridgeDepositRefunded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -5752,61 +5642,62 @@ func (it *FastBridgeBridgeProofProvidedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeBridgeProofProvidedIterator) Error() error { +func (it *FastBridgeBridgeDepositRefundedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeBridgeProofProvidedIterator) Close() error { +func (it *FastBridgeBridgeDepositRefundedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeBridgeProofProvided represents a BridgeProofProvided event raised by the FastBridge contract. -type FastBridgeBridgeProofProvided struct { - TransactionId [32]byte - Relayer common.Address - TransactionHash [32]byte - Raw types.Log // Blockchain specific contextual infos +// FastBridgeBridgeDepositRefunded represents a BridgeDepositRefunded event raised by the FastBridge contract. +type FastBridgeBridgeDepositRefunded struct { + TransactionId [32]byte + To common.Address + Token common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterBridgeProofProvided is a free log retrieval operation binding the contract event 0x4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4. +// FilterBridgeDepositRefunded is a free log retrieval operation binding the contract event 0xb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958. // -// Solidity: event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash) -func (_FastBridge *FastBridgeFilterer) FilterBridgeProofProvided(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address) (*FastBridgeBridgeProofProvidedIterator, error) { +// Solidity: event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount) +func (_FastBridge *FastBridgeFilterer) FilterBridgeDepositRefunded(opts *bind.FilterOpts, transactionId [][32]byte, to []common.Address) (*FastBridgeBridgeDepositRefundedIterator, error) { var transactionIdRule []interface{} for _, transactionIdItem := range transactionId { transactionIdRule = append(transactionIdRule, transactionIdItem) } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) } - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeProofProvided", transactionIdRule, relayerRule) + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeDepositRefunded", transactionIdRule, toRule) if err != nil { return nil, err } - return &FastBridgeBridgeProofProvidedIterator{contract: _FastBridge.contract, event: "BridgeProofProvided", logs: logs, sub: sub}, nil + return &FastBridgeBridgeDepositRefundedIterator{contract: _FastBridge.contract, event: "BridgeDepositRefunded", logs: logs, sub: sub}, nil } -// WatchBridgeProofProvided is a free log subscription operation binding the contract event 0x4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4. +// WatchBridgeDepositRefunded is a free log subscription operation binding the contract event 0xb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958. // -// Solidity: event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash) -func (_FastBridge *FastBridgeFilterer) WatchBridgeProofProvided(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeProofProvided, transactionId [][32]byte, relayer []common.Address) (event.Subscription, error) { +// Solidity: event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount) +func (_FastBridge *FastBridgeFilterer) WatchBridgeDepositRefunded(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeDepositRefunded, transactionId [][32]byte, to []common.Address) (event.Subscription, error) { var transactionIdRule []interface{} for _, transactionIdItem := range transactionId { transactionIdRule = append(transactionIdRule, transactionIdItem) } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) } - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeProofProvided", transactionIdRule, relayerRule) + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeDepositRefunded", transactionIdRule, toRule) if err != nil { return nil, err } @@ -5816,8 +5707,8 @@ func (_FastBridge *FastBridgeFilterer) WatchBridgeProofProvided(opts *bind.Watch select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeBridgeProofProvided) - if err := _FastBridge.contract.UnpackLog(event, "BridgeProofProvided", log); err != nil { + event := new(FastBridgeBridgeDepositRefunded) + if err := _FastBridge.contract.UnpackLog(event, "BridgeDepositRefunded", log); err != nil { return err } event.Raw = log @@ -5838,21 +5729,21 @@ func (_FastBridge *FastBridgeFilterer) WatchBridgeProofProvided(opts *bind.Watch }), nil } -// ParseBridgeProofProvided is a log parse operation binding the contract event 0x4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4. +// ParseBridgeDepositRefunded is a log parse operation binding the contract event 0xb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958. // -// Solidity: event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash) -func (_FastBridge *FastBridgeFilterer) ParseBridgeProofProvided(log types.Log) (*FastBridgeBridgeProofProvided, error) { - event := new(FastBridgeBridgeProofProvided) - if err := _FastBridge.contract.UnpackLog(event, "BridgeProofProvided", log); err != nil { +// Solidity: event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount) +func (_FastBridge *FastBridgeFilterer) ParseBridgeDepositRefunded(log types.Log) (*FastBridgeBridgeDepositRefunded, error) { + event := new(FastBridgeBridgeDepositRefunded) + if err := _FastBridge.contract.UnpackLog(event, "BridgeDepositRefunded", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeBridgeRelayedIterator is returned from FilterBridgeRelayed and is used to iterate over the raw logs and unpacked data for BridgeRelayed events raised by the FastBridge contract. -type FastBridgeBridgeRelayedIterator struct { - Event *FastBridgeBridgeRelayed // Event containing the contract specifics and raw log +// FastBridgeBridgeProofDisputedIterator is returned from FilterBridgeProofDisputed and is used to iterate over the raw logs and unpacked data for BridgeProofDisputed events raised by the FastBridge contract. +type FastBridgeBridgeProofDisputedIterator struct { + Event *FastBridgeBridgeProofDisputed // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -5866,7 +5757,7 @@ type FastBridgeBridgeRelayedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeBridgeRelayedIterator) Next() bool { +func (it *FastBridgeBridgeProofDisputedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -5875,7 +5766,7 @@ func (it *FastBridgeBridgeRelayedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeBridgeRelayed) + it.Event = new(FastBridgeBridgeProofDisputed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -5890,7 +5781,7 @@ func (it *FastBridgeBridgeRelayedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeBridgeRelayed) + it.Event = new(FastBridgeBridgeProofDisputed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -5906,35 +5797,28 @@ func (it *FastBridgeBridgeRelayedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeBridgeRelayedIterator) Error() error { +func (it *FastBridgeBridgeProofDisputedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeBridgeRelayedIterator) Close() error { +func (it *FastBridgeBridgeProofDisputedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeBridgeRelayed represents a BridgeRelayed event raised by the FastBridge contract. -type FastBridgeBridgeRelayed struct { - TransactionId [32]byte - Relayer common.Address - To common.Address - OriginChainId uint32 - OriginToken common.Address - DestToken common.Address - OriginAmount *big.Int - DestAmount *big.Int - ChainGasAmount *big.Int - Raw types.Log // Blockchain specific contextual infos +// FastBridgeBridgeProofDisputed represents a BridgeProofDisputed event raised by the FastBridge contract. +type FastBridgeBridgeProofDisputed struct { + TransactionId [32]byte + Relayer common.Address + Raw types.Log // Blockchain specific contextual infos } -// FilterBridgeRelayed is a free log retrieval operation binding the contract event 0xf8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c. +// FilterBridgeProofDisputed is a free log retrieval operation binding the contract event 0x0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad4. // -// Solidity: event BridgeRelayed(bytes32 indexed transactionId, address indexed relayer, address indexed to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) -func (_FastBridge *FastBridgeFilterer) FilterBridgeRelayed(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address, to []common.Address) (*FastBridgeBridgeRelayedIterator, error) { +// Solidity: event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer) +func (_FastBridge *FastBridgeFilterer) FilterBridgeProofDisputed(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address) (*FastBridgeBridgeProofDisputedIterator, error) { var transactionIdRule []interface{} for _, transactionIdItem := range transactionId { @@ -5944,22 +5828,18 @@ func (_FastBridge *FastBridgeFilterer) FilterBridgeRelayed(opts *bind.FilterOpts for _, relayerItem := range relayer { relayerRule = append(relayerRule, relayerItem) } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeRelayed", transactionIdRule, relayerRule, toRule) + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeProofDisputed", transactionIdRule, relayerRule) if err != nil { return nil, err } - return &FastBridgeBridgeRelayedIterator{contract: _FastBridge.contract, event: "BridgeRelayed", logs: logs, sub: sub}, nil + return &FastBridgeBridgeProofDisputedIterator{contract: _FastBridge.contract, event: "BridgeProofDisputed", logs: logs, sub: sub}, nil } -// WatchBridgeRelayed is a free log subscription operation binding the contract event 0xf8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c. +// WatchBridgeProofDisputed is a free log subscription operation binding the contract event 0x0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad4. // -// Solidity: event BridgeRelayed(bytes32 indexed transactionId, address indexed relayer, address indexed to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) -func (_FastBridge *FastBridgeFilterer) WatchBridgeRelayed(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeRelayed, transactionId [][32]byte, relayer []common.Address, to []common.Address) (event.Subscription, error) { +// Solidity: event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer) +func (_FastBridge *FastBridgeFilterer) WatchBridgeProofDisputed(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeProofDisputed, transactionId [][32]byte, relayer []common.Address) (event.Subscription, error) { var transactionIdRule []interface{} for _, transactionIdItem := range transactionId { @@ -5969,12 +5849,8 @@ func (_FastBridge *FastBridgeFilterer) WatchBridgeRelayed(opts *bind.WatchOpts, for _, relayerItem := range relayer { relayerRule = append(relayerRule, relayerItem) } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeRelayed", transactionIdRule, relayerRule, toRule) + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeProofDisputed", transactionIdRule, relayerRule) if err != nil { return nil, err } @@ -5984,8 +5860,8 @@ func (_FastBridge *FastBridgeFilterer) WatchBridgeRelayed(opts *bind.WatchOpts, select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeBridgeRelayed) - if err := _FastBridge.contract.UnpackLog(event, "BridgeRelayed", log); err != nil { + event := new(FastBridgeBridgeProofDisputed) + if err := _FastBridge.contract.UnpackLog(event, "BridgeProofDisputed", log); err != nil { return err } event.Raw = log @@ -6006,21 +5882,21 @@ func (_FastBridge *FastBridgeFilterer) WatchBridgeRelayed(opts *bind.WatchOpts, }), nil } -// ParseBridgeRelayed is a log parse operation binding the contract event 0xf8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c. +// ParseBridgeProofDisputed is a log parse operation binding the contract event 0x0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad4. // -// Solidity: event BridgeRelayed(bytes32 indexed transactionId, address indexed relayer, address indexed to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) -func (_FastBridge *FastBridgeFilterer) ParseBridgeRelayed(log types.Log) (*FastBridgeBridgeRelayed, error) { - event := new(FastBridgeBridgeRelayed) - if err := _FastBridge.contract.UnpackLog(event, "BridgeRelayed", log); err != nil { +// Solidity: event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer) +func (_FastBridge *FastBridgeFilterer) ParseBridgeProofDisputed(log types.Log) (*FastBridgeBridgeProofDisputed, error) { + event := new(FastBridgeBridgeProofDisputed) + if err := _FastBridge.contract.UnpackLog(event, "BridgeProofDisputed", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeBridgeRequestedIterator is returned from FilterBridgeRequested and is used to iterate over the raw logs and unpacked data for BridgeRequested events raised by the FastBridge contract. -type FastBridgeBridgeRequestedIterator struct { - Event *FastBridgeBridgeRequested // Event containing the contract specifics and raw log +// FastBridgeBridgeProofProvidedIterator is returned from FilterBridgeProofProvided and is used to iterate over the raw logs and unpacked data for BridgeProofProvided events raised by the FastBridge contract. +type FastBridgeBridgeProofProvidedIterator struct { + Event *FastBridgeBridgeProofProvided // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -6034,7 +5910,7 @@ type FastBridgeBridgeRequestedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeBridgeRequestedIterator) Next() bool { +func (it *FastBridgeBridgeProofProvidedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -6043,7 +5919,7 @@ func (it *FastBridgeBridgeRequestedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeBridgeRequested) + it.Event = new(FastBridgeBridgeProofProvided) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6058,7 +5934,7 @@ func (it *FastBridgeBridgeRequestedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeBridgeRequested) + it.Event = new(FastBridgeBridgeProofProvided) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6074,67 +5950,61 @@ func (it *FastBridgeBridgeRequestedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeBridgeRequestedIterator) Error() error { +func (it *FastBridgeBridgeProofProvidedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeBridgeRequestedIterator) Close() error { +func (it *FastBridgeBridgeProofProvidedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeBridgeRequested represents a BridgeRequested event raised by the FastBridge contract. -type FastBridgeBridgeRequested struct { - TransactionId [32]byte - Sender common.Address - Request []byte - DestChainId uint32 - OriginToken common.Address - DestToken common.Address - OriginAmount *big.Int - DestAmount *big.Int - SendChainGas bool - Raw types.Log // Blockchain specific contextual infos +// FastBridgeBridgeProofProvided represents a BridgeProofProvided event raised by the FastBridge contract. +type FastBridgeBridgeProofProvided struct { + TransactionId [32]byte + Relayer common.Address + TransactionHash [32]byte + Raw types.Log // Blockchain specific contextual infos } -// FilterBridgeRequested is a free log retrieval operation binding the contract event 0x120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a. +// FilterBridgeProofProvided is a free log retrieval operation binding the contract event 0x4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4. // -// Solidity: event BridgeRequested(bytes32 indexed transactionId, address indexed sender, bytes request, uint32 destChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, bool sendChainGas) -func (_FastBridge *FastBridgeFilterer) FilterBridgeRequested(opts *bind.FilterOpts, transactionId [][32]byte, sender []common.Address) (*FastBridgeBridgeRequestedIterator, error) { +// Solidity: event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash) +func (_FastBridge *FastBridgeFilterer) FilterBridgeProofProvided(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address) (*FastBridgeBridgeProofProvidedIterator, error) { var transactionIdRule []interface{} for _, transactionIdItem := range transactionId { transactionIdRule = append(transactionIdRule, transactionIdItem) } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) } - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeRequested", transactionIdRule, senderRule) + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeProofProvided", transactionIdRule, relayerRule) if err != nil { return nil, err } - return &FastBridgeBridgeRequestedIterator{contract: _FastBridge.contract, event: "BridgeRequested", logs: logs, sub: sub}, nil + return &FastBridgeBridgeProofProvidedIterator{contract: _FastBridge.contract, event: "BridgeProofProvided", logs: logs, sub: sub}, nil } -// WatchBridgeRequested is a free log subscription operation binding the contract event 0x120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a. +// WatchBridgeProofProvided is a free log subscription operation binding the contract event 0x4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4. // -// Solidity: event BridgeRequested(bytes32 indexed transactionId, address indexed sender, bytes request, uint32 destChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, bool sendChainGas) -func (_FastBridge *FastBridgeFilterer) WatchBridgeRequested(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeRequested, transactionId [][32]byte, sender []common.Address) (event.Subscription, error) { +// Solidity: event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash) +func (_FastBridge *FastBridgeFilterer) WatchBridgeProofProvided(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeProofProvided, transactionId [][32]byte, relayer []common.Address) (event.Subscription, error) { var transactionIdRule []interface{} for _, transactionIdItem := range transactionId { transactionIdRule = append(transactionIdRule, transactionIdItem) } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) } - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeRequested", transactionIdRule, senderRule) + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeProofProvided", transactionIdRule, relayerRule) if err != nil { return nil, err } @@ -6144,8 +6014,8 @@ func (_FastBridge *FastBridgeFilterer) WatchBridgeRequested(opts *bind.WatchOpts select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeBridgeRequested) - if err := _FastBridge.contract.UnpackLog(event, "BridgeRequested", log); err != nil { + event := new(FastBridgeBridgeProofProvided) + if err := _FastBridge.contract.UnpackLog(event, "BridgeProofProvided", log); err != nil { return err } event.Raw = log @@ -6166,21 +6036,21 @@ func (_FastBridge *FastBridgeFilterer) WatchBridgeRequested(opts *bind.WatchOpts }), nil } -// ParseBridgeRequested is a log parse operation binding the contract event 0x120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a. +// ParseBridgeProofProvided is a log parse operation binding the contract event 0x4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4. // -// Solidity: event BridgeRequested(bytes32 indexed transactionId, address indexed sender, bytes request, uint32 destChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, bool sendChainGas) -func (_FastBridge *FastBridgeFilterer) ParseBridgeRequested(log types.Log) (*FastBridgeBridgeRequested, error) { - event := new(FastBridgeBridgeRequested) - if err := _FastBridge.contract.UnpackLog(event, "BridgeRequested", log); err != nil { +// Solidity: event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash) +func (_FastBridge *FastBridgeFilterer) ParseBridgeProofProvided(log types.Log) (*FastBridgeBridgeProofProvided, error) { + event := new(FastBridgeBridgeProofProvided) + if err := _FastBridge.contract.UnpackLog(event, "BridgeProofProvided", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeChainGasAmountUpdatedIterator is returned from FilterChainGasAmountUpdated and is used to iterate over the raw logs and unpacked data for ChainGasAmountUpdated events raised by the FastBridge contract. -type FastBridgeChainGasAmountUpdatedIterator struct { - Event *FastBridgeChainGasAmountUpdated // Event containing the contract specifics and raw log +// FastBridgeBridgeRelayedIterator is returned from FilterBridgeRelayed and is used to iterate over the raw logs and unpacked data for BridgeRelayed events raised by the FastBridge contract. +type FastBridgeBridgeRelayedIterator struct { + Event *FastBridgeBridgeRelayed // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -6194,7 +6064,7 @@ type FastBridgeChainGasAmountUpdatedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeChainGasAmountUpdatedIterator) Next() bool { +func (it *FastBridgeBridgeRelayedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -6203,7 +6073,7 @@ func (it *FastBridgeChainGasAmountUpdatedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeChainGasAmountUpdated) + it.Event = new(FastBridgeBridgeRelayed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6218,7 +6088,7 @@ func (it *FastBridgeChainGasAmountUpdatedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeChainGasAmountUpdated) + it.Event = new(FastBridgeBridgeRelayed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6234,42 +6104,75 @@ func (it *FastBridgeChainGasAmountUpdatedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeChainGasAmountUpdatedIterator) Error() error { +func (it *FastBridgeBridgeRelayedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeChainGasAmountUpdatedIterator) Close() error { +func (it *FastBridgeBridgeRelayedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeChainGasAmountUpdated represents a ChainGasAmountUpdated event raised by the FastBridge contract. -type FastBridgeChainGasAmountUpdated struct { - OldChainGasAmount *big.Int - NewChainGasAmount *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterChainGasAmountUpdated is a free log retrieval operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. -// -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_FastBridge *FastBridgeFilterer) FilterChainGasAmountUpdated(opts *bind.FilterOpts) (*FastBridgeChainGasAmountUpdatedIterator, error) { +// FastBridgeBridgeRelayed represents a BridgeRelayed event raised by the FastBridge contract. +type FastBridgeBridgeRelayed struct { + TransactionId [32]byte + Relayer common.Address + To common.Address + OriginChainId uint32 + OriginToken common.Address + DestToken common.Address + OriginAmount *big.Int + DestAmount *big.Int + ChainGasAmount *big.Int + Raw types.Log // Blockchain specific contextual infos +} - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "ChainGasAmountUpdated") +// FilterBridgeRelayed is a free log retrieval operation binding the contract event 0xf8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c. +// +// Solidity: event BridgeRelayed(bytes32 indexed transactionId, address indexed relayer, address indexed to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) +func (_FastBridge *FastBridgeFilterer) FilterBridgeRelayed(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address, to []common.Address) (*FastBridgeBridgeRelayedIterator, error) { + + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeRelayed", transactionIdRule, relayerRule, toRule) if err != nil { return nil, err } - return &FastBridgeChainGasAmountUpdatedIterator{contract: _FastBridge.contract, event: "ChainGasAmountUpdated", logs: logs, sub: sub}, nil + return &FastBridgeBridgeRelayedIterator{contract: _FastBridge.contract, event: "BridgeRelayed", logs: logs, sub: sub}, nil } -// WatchChainGasAmountUpdated is a free log subscription operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. +// WatchBridgeRelayed is a free log subscription operation binding the contract event 0xf8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_FastBridge *FastBridgeFilterer) WatchChainGasAmountUpdated(opts *bind.WatchOpts, sink chan<- *FastBridgeChainGasAmountUpdated) (event.Subscription, error) { +// Solidity: event BridgeRelayed(bytes32 indexed transactionId, address indexed relayer, address indexed to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) +func (_FastBridge *FastBridgeFilterer) WatchBridgeRelayed(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeRelayed, transactionId [][32]byte, relayer []common.Address, to []common.Address) (event.Subscription, error) { - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "ChainGasAmountUpdated") + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeRelayed", transactionIdRule, relayerRule, toRule) if err != nil { return nil, err } @@ -6279,8 +6182,8 @@ func (_FastBridge *FastBridgeFilterer) WatchChainGasAmountUpdated(opts *bind.Wat select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeChainGasAmountUpdated) - if err := _FastBridge.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { + event := new(FastBridgeBridgeRelayed) + if err := _FastBridge.contract.UnpackLog(event, "BridgeRelayed", log); err != nil { return err } event.Raw = log @@ -6301,21 +6204,21 @@ func (_FastBridge *FastBridgeFilterer) WatchChainGasAmountUpdated(opts *bind.Wat }), nil } -// ParseChainGasAmountUpdated is a log parse operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. +// ParseBridgeRelayed is a log parse operation binding the contract event 0xf8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_FastBridge *FastBridgeFilterer) ParseChainGasAmountUpdated(log types.Log) (*FastBridgeChainGasAmountUpdated, error) { - event := new(FastBridgeChainGasAmountUpdated) - if err := _FastBridge.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { +// Solidity: event BridgeRelayed(bytes32 indexed transactionId, address indexed relayer, address indexed to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) +func (_FastBridge *FastBridgeFilterer) ParseBridgeRelayed(log types.Log) (*FastBridgeBridgeRelayed, error) { + event := new(FastBridgeBridgeRelayed) + if err := _FastBridge.contract.UnpackLog(event, "BridgeRelayed", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeFeeRateUpdatedIterator is returned from FilterFeeRateUpdated and is used to iterate over the raw logs and unpacked data for FeeRateUpdated events raised by the FastBridge contract. -type FastBridgeFeeRateUpdatedIterator struct { - Event *FastBridgeFeeRateUpdated // Event containing the contract specifics and raw log +// FastBridgeBridgeRequestedIterator is returned from FilterBridgeRequested and is used to iterate over the raw logs and unpacked data for BridgeRequested events raised by the FastBridge contract. +type FastBridgeBridgeRequestedIterator struct { + Event *FastBridgeBridgeRequested // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -6329,7 +6232,7 @@ type FastBridgeFeeRateUpdatedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeFeeRateUpdatedIterator) Next() bool { +func (it *FastBridgeBridgeRequestedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -6338,7 +6241,7 @@ func (it *FastBridgeFeeRateUpdatedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeFeeRateUpdated) + it.Event = new(FastBridgeBridgeRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6353,7 +6256,7 @@ func (it *FastBridgeFeeRateUpdatedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeFeeRateUpdated) + it.Event = new(FastBridgeBridgeRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6369,42 +6272,67 @@ func (it *FastBridgeFeeRateUpdatedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeFeeRateUpdatedIterator) Error() error { +func (it *FastBridgeBridgeRequestedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeFeeRateUpdatedIterator) Close() error { +func (it *FastBridgeBridgeRequestedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeFeeRateUpdated represents a FeeRateUpdated event raised by the FastBridge contract. -type FastBridgeFeeRateUpdated struct { - OldFeeRate *big.Int - NewFeeRate *big.Int - Raw types.Log // Blockchain specific contextual infos +// FastBridgeBridgeRequested represents a BridgeRequested event raised by the FastBridge contract. +type FastBridgeBridgeRequested struct { + TransactionId [32]byte + Sender common.Address + Request []byte + DestChainId uint32 + OriginToken common.Address + DestToken common.Address + OriginAmount *big.Int + DestAmount *big.Int + SendChainGas bool + Raw types.Log // Blockchain specific contextual infos } -// FilterFeeRateUpdated is a free log retrieval operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// FilterBridgeRequested is a free log retrieval operation binding the contract event 0x120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a. // -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_FastBridge *FastBridgeFilterer) FilterFeeRateUpdated(opts *bind.FilterOpts) (*FastBridgeFeeRateUpdatedIterator, error) { +// Solidity: event BridgeRequested(bytes32 indexed transactionId, address indexed sender, bytes request, uint32 destChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, bool sendChainGas) +func (_FastBridge *FastBridgeFilterer) FilterBridgeRequested(opts *bind.FilterOpts, transactionId [][32]byte, sender []common.Address) (*FastBridgeBridgeRequestedIterator, error) { - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "FeeRateUpdated") + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "BridgeRequested", transactionIdRule, senderRule) if err != nil { return nil, err } - return &FastBridgeFeeRateUpdatedIterator{contract: _FastBridge.contract, event: "FeeRateUpdated", logs: logs, sub: sub}, nil + return &FastBridgeBridgeRequestedIterator{contract: _FastBridge.contract, event: "BridgeRequested", logs: logs, sub: sub}, nil } -// WatchFeeRateUpdated is a free log subscription operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// WatchBridgeRequested is a free log subscription operation binding the contract event 0x120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a. // -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_FastBridge *FastBridgeFilterer) WatchFeeRateUpdated(opts *bind.WatchOpts, sink chan<- *FastBridgeFeeRateUpdated) (event.Subscription, error) { +// Solidity: event BridgeRequested(bytes32 indexed transactionId, address indexed sender, bytes request, uint32 destChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, bool sendChainGas) +func (_FastBridge *FastBridgeFilterer) WatchBridgeRequested(opts *bind.WatchOpts, sink chan<- *FastBridgeBridgeRequested, transactionId [][32]byte, sender []common.Address) (event.Subscription, error) { - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "FeeRateUpdated") + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "BridgeRequested", transactionIdRule, senderRule) if err != nil { return nil, err } @@ -6414,8 +6342,8 @@ func (_FastBridge *FastBridgeFilterer) WatchFeeRateUpdated(opts *bind.WatchOpts, select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeFeeRateUpdated) - if err := _FastBridge.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { + event := new(FastBridgeBridgeRequested) + if err := _FastBridge.contract.UnpackLog(event, "BridgeRequested", log); err != nil { return err } event.Raw = log @@ -6436,21 +6364,21 @@ func (_FastBridge *FastBridgeFilterer) WatchFeeRateUpdated(opts *bind.WatchOpts, }), nil } -// ParseFeeRateUpdated is a log parse operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// ParseBridgeRequested is a log parse operation binding the contract event 0x120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a. // -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_FastBridge *FastBridgeFilterer) ParseFeeRateUpdated(log types.Log) (*FastBridgeFeeRateUpdated, error) { - event := new(FastBridgeFeeRateUpdated) - if err := _FastBridge.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { +// Solidity: event BridgeRequested(bytes32 indexed transactionId, address indexed sender, bytes request, uint32 destChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, bool sendChainGas) +func (_FastBridge *FastBridgeFilterer) ParseBridgeRequested(log types.Log) (*FastBridgeBridgeRequested, error) { + event := new(FastBridgeBridgeRequested) + if err := _FastBridge.contract.UnpackLog(event, "BridgeRequested", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeFeesSweptIterator is returned from FilterFeesSwept and is used to iterate over the raw logs and unpacked data for FeesSwept events raised by the FastBridge contract. -type FastBridgeFeesSweptIterator struct { - Event *FastBridgeFeesSwept // Event containing the contract specifics and raw log +// FastBridgeChainGasAmountUpdatedIterator is returned from FilterChainGasAmountUpdated and is used to iterate over the raw logs and unpacked data for ChainGasAmountUpdated events raised by the FastBridge contract. +type FastBridgeChainGasAmountUpdatedIterator struct { + Event *FastBridgeChainGasAmountUpdated // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -6464,7 +6392,7 @@ type FastBridgeFeesSweptIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeFeesSweptIterator) Next() bool { +func (it *FastBridgeChainGasAmountUpdatedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -6473,7 +6401,7 @@ func (it *FastBridgeFeesSweptIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeFeesSwept) + it.Event = new(FastBridgeChainGasAmountUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6488,7 +6416,7 @@ func (it *FastBridgeFeesSweptIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeFeesSwept) + it.Event = new(FastBridgeChainGasAmountUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6504,43 +6432,42 @@ func (it *FastBridgeFeesSweptIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeFeesSweptIterator) Error() error { +func (it *FastBridgeChainGasAmountUpdatedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeFeesSweptIterator) Close() error { +func (it *FastBridgeChainGasAmountUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeFeesSwept represents a FeesSwept event raised by the FastBridge contract. -type FastBridgeFeesSwept struct { - Token common.Address - Recipient common.Address - Amount *big.Int - Raw types.Log // Blockchain specific contextual infos +// FastBridgeChainGasAmountUpdated represents a ChainGasAmountUpdated event raised by the FastBridge contract. +type FastBridgeChainGasAmountUpdated struct { + OldChainGasAmount *big.Int + NewChainGasAmount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterFeesSwept is a free log retrieval operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// FilterChainGasAmountUpdated is a free log retrieval operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_FastBridge *FastBridgeFilterer) FilterFeesSwept(opts *bind.FilterOpts) (*FastBridgeFeesSweptIterator, error) { +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_FastBridge *FastBridgeFilterer) FilterChainGasAmountUpdated(opts *bind.FilterOpts) (*FastBridgeChainGasAmountUpdatedIterator, error) { - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "FeesSwept") + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "ChainGasAmountUpdated") if err != nil { return nil, err } - return &FastBridgeFeesSweptIterator{contract: _FastBridge.contract, event: "FeesSwept", logs: logs, sub: sub}, nil + return &FastBridgeChainGasAmountUpdatedIterator{contract: _FastBridge.contract, event: "ChainGasAmountUpdated", logs: logs, sub: sub}, nil } -// WatchFeesSwept is a free log subscription operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// WatchChainGasAmountUpdated is a free log subscription operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_FastBridge *FastBridgeFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink chan<- *FastBridgeFeesSwept) (event.Subscription, error) { +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_FastBridge *FastBridgeFilterer) WatchChainGasAmountUpdated(opts *bind.WatchOpts, sink chan<- *FastBridgeChainGasAmountUpdated) (event.Subscription, error) { - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "FeesSwept") + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "ChainGasAmountUpdated") if err != nil { return nil, err } @@ -6550,8 +6477,8 @@ func (_FastBridge *FastBridgeFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeFeesSwept) - if err := _FastBridge.contract.UnpackLog(event, "FeesSwept", log); err != nil { + event := new(FastBridgeChainGasAmountUpdated) + if err := _FastBridge.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { return err } event.Raw = log @@ -6572,21 +6499,21 @@ func (_FastBridge *FastBridgeFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink }), nil } -// ParseFeesSwept is a log parse operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// ParseChainGasAmountUpdated is a log parse operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_FastBridge *FastBridgeFilterer) ParseFeesSwept(log types.Log) (*FastBridgeFeesSwept, error) { - event := new(FastBridgeFeesSwept) - if err := _FastBridge.contract.UnpackLog(event, "FeesSwept", log); err != nil { +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_FastBridge *FastBridgeFilterer) ParseChainGasAmountUpdated(log types.Log) (*FastBridgeChainGasAmountUpdated, error) { + event := new(FastBridgeChainGasAmountUpdated) + if err := _FastBridge.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeGovernorAddedIterator is returned from FilterGovernorAdded and is used to iterate over the raw logs and unpacked data for GovernorAdded events raised by the FastBridge contract. -type FastBridgeGovernorAddedIterator struct { - Event *FastBridgeGovernorAdded // Event containing the contract specifics and raw log +// FastBridgeFeeRateUpdatedIterator is returned from FilterFeeRateUpdated and is used to iterate over the raw logs and unpacked data for FeeRateUpdated events raised by the FastBridge contract. +type FastBridgeFeeRateUpdatedIterator struct { + Event *FastBridgeFeeRateUpdated // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -6600,7 +6527,7 @@ type FastBridgeGovernorAddedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeGovernorAddedIterator) Next() bool { +func (it *FastBridgeFeeRateUpdatedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -6609,7 +6536,7 @@ func (it *FastBridgeGovernorAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeGovernorAdded) + it.Event = new(FastBridgeFeeRateUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6624,7 +6551,7 @@ func (it *FastBridgeGovernorAddedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeGovernorAdded) + it.Event = new(FastBridgeFeeRateUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6640,41 +6567,42 @@ func (it *FastBridgeGovernorAddedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeGovernorAddedIterator) Error() error { +func (it *FastBridgeFeeRateUpdatedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeGovernorAddedIterator) Close() error { +func (it *FastBridgeFeeRateUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeGovernorAdded represents a GovernorAdded event raised by the FastBridge contract. -type FastBridgeGovernorAdded struct { - Governor common.Address - Raw types.Log // Blockchain specific contextual infos +// FastBridgeFeeRateUpdated represents a FeeRateUpdated event raised by the FastBridge contract. +type FastBridgeFeeRateUpdated struct { + OldFeeRate *big.Int + NewFeeRate *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterGovernorAdded is a free log retrieval operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. +// FilterFeeRateUpdated is a free log retrieval operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. // -// Solidity: event GovernorAdded(address governor) -func (_FastBridge *FastBridgeFilterer) FilterGovernorAdded(opts *bind.FilterOpts) (*FastBridgeGovernorAddedIterator, error) { +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_FastBridge *FastBridgeFilterer) FilterFeeRateUpdated(opts *bind.FilterOpts) (*FastBridgeFeeRateUpdatedIterator, error) { - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "GovernorAdded") + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "FeeRateUpdated") if err != nil { return nil, err } - return &FastBridgeGovernorAddedIterator{contract: _FastBridge.contract, event: "GovernorAdded", logs: logs, sub: sub}, nil + return &FastBridgeFeeRateUpdatedIterator{contract: _FastBridge.contract, event: "FeeRateUpdated", logs: logs, sub: sub}, nil } -// WatchGovernorAdded is a free log subscription operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. +// WatchFeeRateUpdated is a free log subscription operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. // -// Solidity: event GovernorAdded(address governor) -func (_FastBridge *FastBridgeFilterer) WatchGovernorAdded(opts *bind.WatchOpts, sink chan<- *FastBridgeGovernorAdded) (event.Subscription, error) { +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_FastBridge *FastBridgeFilterer) WatchFeeRateUpdated(opts *bind.WatchOpts, sink chan<- *FastBridgeFeeRateUpdated) (event.Subscription, error) { - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "GovernorAdded") + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "FeeRateUpdated") if err != nil { return nil, err } @@ -6684,8 +6612,8 @@ func (_FastBridge *FastBridgeFilterer) WatchGovernorAdded(opts *bind.WatchOpts, select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeGovernorAdded) - if err := _FastBridge.contract.UnpackLog(event, "GovernorAdded", log); err != nil { + event := new(FastBridgeFeeRateUpdated) + if err := _FastBridge.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { return err } event.Raw = log @@ -6706,21 +6634,21 @@ func (_FastBridge *FastBridgeFilterer) WatchGovernorAdded(opts *bind.WatchOpts, }), nil } -// ParseGovernorAdded is a log parse operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. +// ParseFeeRateUpdated is a log parse operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. // -// Solidity: event GovernorAdded(address governor) -func (_FastBridge *FastBridgeFilterer) ParseGovernorAdded(log types.Log) (*FastBridgeGovernorAdded, error) { - event := new(FastBridgeGovernorAdded) - if err := _FastBridge.contract.UnpackLog(event, "GovernorAdded", log); err != nil { +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_FastBridge *FastBridgeFilterer) ParseFeeRateUpdated(log types.Log) (*FastBridgeFeeRateUpdated, error) { + event := new(FastBridgeFeeRateUpdated) + if err := _FastBridge.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeGovernorRemovedIterator is returned from FilterGovernorRemoved and is used to iterate over the raw logs and unpacked data for GovernorRemoved events raised by the FastBridge contract. -type FastBridgeGovernorRemovedIterator struct { - Event *FastBridgeGovernorRemoved // Event containing the contract specifics and raw log +// FastBridgeFeesSweptIterator is returned from FilterFeesSwept and is used to iterate over the raw logs and unpacked data for FeesSwept events raised by the FastBridge contract. +type FastBridgeFeesSweptIterator struct { + Event *FastBridgeFeesSwept // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -6734,7 +6662,7 @@ type FastBridgeGovernorRemovedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeGovernorRemovedIterator) Next() bool { +func (it *FastBridgeFeesSweptIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -6743,7 +6671,7 @@ func (it *FastBridgeGovernorRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeGovernorRemoved) + it.Event = new(FastBridgeFeesSwept) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6758,7 +6686,7 @@ func (it *FastBridgeGovernorRemovedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeGovernorRemoved) + it.Event = new(FastBridgeFeesSwept) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6774,41 +6702,43 @@ func (it *FastBridgeGovernorRemovedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeGovernorRemovedIterator) Error() error { +func (it *FastBridgeFeesSweptIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeGovernorRemovedIterator) Close() error { +func (it *FastBridgeFeesSweptIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeGovernorRemoved represents a GovernorRemoved event raised by the FastBridge contract. -type FastBridgeGovernorRemoved struct { - Governor common.Address - Raw types.Log // Blockchain specific contextual infos +// FastBridgeFeesSwept represents a FeesSwept event raised by the FastBridge contract. +type FastBridgeFeesSwept struct { + Token common.Address + Recipient common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterGovernorRemoved is a free log retrieval operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. +// FilterFeesSwept is a free log retrieval operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. // -// Solidity: event GovernorRemoved(address governor) -func (_FastBridge *FastBridgeFilterer) FilterGovernorRemoved(opts *bind.FilterOpts) (*FastBridgeGovernorRemovedIterator, error) { +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_FastBridge *FastBridgeFilterer) FilterFeesSwept(opts *bind.FilterOpts) (*FastBridgeFeesSweptIterator, error) { - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "GovernorRemoved") + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "FeesSwept") if err != nil { return nil, err } - return &FastBridgeGovernorRemovedIterator{contract: _FastBridge.contract, event: "GovernorRemoved", logs: logs, sub: sub}, nil + return &FastBridgeFeesSweptIterator{contract: _FastBridge.contract, event: "FeesSwept", logs: logs, sub: sub}, nil } -// WatchGovernorRemoved is a free log subscription operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. +// WatchFeesSwept is a free log subscription operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. // -// Solidity: event GovernorRemoved(address governor) -func (_FastBridge *FastBridgeFilterer) WatchGovernorRemoved(opts *bind.WatchOpts, sink chan<- *FastBridgeGovernorRemoved) (event.Subscription, error) { +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_FastBridge *FastBridgeFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink chan<- *FastBridgeFeesSwept) (event.Subscription, error) { - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "GovernorRemoved") + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "FeesSwept") if err != nil { return nil, err } @@ -6818,8 +6748,8 @@ func (_FastBridge *FastBridgeFilterer) WatchGovernorRemoved(opts *bind.WatchOpts select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeGovernorRemoved) - if err := _FastBridge.contract.UnpackLog(event, "GovernorRemoved", log); err != nil { + event := new(FastBridgeFeesSwept) + if err := _FastBridge.contract.UnpackLog(event, "FeesSwept", log); err != nil { return err } event.Raw = log @@ -6840,21 +6770,21 @@ func (_FastBridge *FastBridgeFilterer) WatchGovernorRemoved(opts *bind.WatchOpts }), nil } -// ParseGovernorRemoved is a log parse operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. +// ParseFeesSwept is a log parse operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. // -// Solidity: event GovernorRemoved(address governor) -func (_FastBridge *FastBridgeFilterer) ParseGovernorRemoved(log types.Log) (*FastBridgeGovernorRemoved, error) { - event := new(FastBridgeGovernorRemoved) - if err := _FastBridge.contract.UnpackLog(event, "GovernorRemoved", log); err != nil { +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_FastBridge *FastBridgeFilterer) ParseFeesSwept(log types.Log) (*FastBridgeFeesSwept, error) { + event := new(FastBridgeFeesSwept) + if err := _FastBridge.contract.UnpackLog(event, "FeesSwept", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeGuardAddedIterator is returned from FilterGuardAdded and is used to iterate over the raw logs and unpacked data for GuardAdded events raised by the FastBridge contract. -type FastBridgeGuardAddedIterator struct { - Event *FastBridgeGuardAdded // Event containing the contract specifics and raw log +// FastBridgeRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the FastBridge contract. +type FastBridgeRoleAdminChangedIterator struct { + Event *FastBridgeRoleAdminChanged // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -6868,7 +6798,7 @@ type FastBridgeGuardAddedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeGuardAddedIterator) Next() bool { +func (it *FastBridgeRoleAdminChangedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -6877,7 +6807,7 @@ func (it *FastBridgeGuardAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeGuardAdded) + it.Event = new(FastBridgeRoleAdminChanged) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6892,7 +6822,7 @@ func (it *FastBridgeGuardAddedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeGuardAdded) + it.Event = new(FastBridgeRoleAdminChanged) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -6908,41 +6838,69 @@ func (it *FastBridgeGuardAddedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeGuardAddedIterator) Error() error { +func (it *FastBridgeRoleAdminChangedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeGuardAddedIterator) Close() error { +func (it *FastBridgeRoleAdminChangedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeGuardAdded represents a GuardAdded event raised by the FastBridge contract. -type FastBridgeGuardAdded struct { - Guard common.Address - Raw types.Log // Blockchain specific contextual infos +// FastBridgeRoleAdminChanged represents a RoleAdminChanged event raised by the FastBridge contract. +type FastBridgeRoleAdminChanged struct { + Role [32]byte + PreviousAdminRole [32]byte + NewAdminRole [32]byte + Raw types.Log // Blockchain specific contextual infos } -// FilterGuardAdded is a free log retrieval operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. // -// Solidity: event GuardAdded(address guard) -func (_FastBridge *FastBridgeFilterer) FilterGuardAdded(opts *bind.FilterOpts) (*FastBridgeGuardAddedIterator, error) { +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_FastBridge *FastBridgeFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*FastBridgeRoleAdminChangedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + } - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "GuardAdded") + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { return nil, err } - return &FastBridgeGuardAddedIterator{contract: _FastBridge.contract, event: "GuardAdded", logs: logs, sub: sub}, nil + return &FastBridgeRoleAdminChangedIterator{contract: _FastBridge.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil } -// WatchGuardAdded is a free log subscription operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. // -// Solidity: event GuardAdded(address guard) -func (_FastBridge *FastBridgeFilterer) WatchGuardAdded(opts *bind.WatchOpts, sink chan<- *FastBridgeGuardAdded) (event.Subscription, error) { +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_FastBridge *FastBridgeFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *FastBridgeRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + } - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "GuardAdded") + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { return nil, err } @@ -6952,8 +6910,8 @@ func (_FastBridge *FastBridgeFilterer) WatchGuardAdded(opts *bind.WatchOpts, sin select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeGuardAdded) - if err := _FastBridge.contract.UnpackLog(event, "GuardAdded", log); err != nil { + event := new(FastBridgeRoleAdminChanged) + if err := _FastBridge.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { return err } event.Raw = log @@ -6974,21 +6932,21 @@ func (_FastBridge *FastBridgeFilterer) WatchGuardAdded(opts *bind.WatchOpts, sin }), nil } -// ParseGuardAdded is a log parse operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. // -// Solidity: event GuardAdded(address guard) -func (_FastBridge *FastBridgeFilterer) ParseGuardAdded(log types.Log) (*FastBridgeGuardAdded, error) { - event := new(FastBridgeGuardAdded) - if err := _FastBridge.contract.UnpackLog(event, "GuardAdded", log); err != nil { +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_FastBridge *FastBridgeFilterer) ParseRoleAdminChanged(log types.Log) (*FastBridgeRoleAdminChanged, error) { + event := new(FastBridgeRoleAdminChanged) + if err := _FastBridge.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeGuardRemovedIterator is returned from FilterGuardRemoved and is used to iterate over the raw logs and unpacked data for GuardRemoved events raised by the FastBridge contract. -type FastBridgeGuardRemovedIterator struct { - Event *FastBridgeGuardRemoved // Event containing the contract specifics and raw log +// FastBridgeRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the FastBridge contract. +type FastBridgeRoleGrantedIterator struct { + Event *FastBridgeRoleGranted // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -7002,7 +6960,7 @@ type FastBridgeGuardRemovedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeGuardRemovedIterator) Next() bool { +func (it *FastBridgeRoleGrantedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -7011,7 +6969,7 @@ func (it *FastBridgeGuardRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeGuardRemoved) + it.Event = new(FastBridgeRoleGranted) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -7026,7 +6984,7 @@ func (it *FastBridgeGuardRemovedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeGuardRemoved) + it.Event = new(FastBridgeRoleGranted) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -7042,41 +7000,69 @@ func (it *FastBridgeGuardRemovedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeGuardRemovedIterator) Error() error { +func (it *FastBridgeRoleGrantedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeGuardRemovedIterator) Close() error { +func (it *FastBridgeRoleGrantedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeGuardRemoved represents a GuardRemoved event raised by the FastBridge contract. -type FastBridgeGuardRemoved struct { - Guard common.Address - Raw types.Log // Blockchain specific contextual infos +// FastBridgeRoleGranted represents a RoleGranted event raised by the FastBridge contract. +type FastBridgeRoleGranted struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos } -// FilterGuardRemoved is a free log retrieval operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. // -// Solidity: event GuardRemoved(address guard) -func (_FastBridge *FastBridgeFilterer) FilterGuardRemoved(opts *bind.FilterOpts) (*FastBridgeGuardRemovedIterator, error) { +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_FastBridge *FastBridgeFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*FastBridgeRoleGrantedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "GuardRemoved") + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) if err != nil { return nil, err } - return &FastBridgeGuardRemovedIterator{contract: _FastBridge.contract, event: "GuardRemoved", logs: logs, sub: sub}, nil + return &FastBridgeRoleGrantedIterator{contract: _FastBridge.contract, event: "RoleGranted", logs: logs, sub: sub}, nil } -// WatchGuardRemoved is a free log subscription operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. // -// Solidity: event GuardRemoved(address guard) -func (_FastBridge *FastBridgeFilterer) WatchGuardRemoved(opts *bind.WatchOpts, sink chan<- *FastBridgeGuardRemoved) (event.Subscription, error) { +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_FastBridge *FastBridgeFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *FastBridgeRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "GuardRemoved") + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) if err != nil { return nil, err } @@ -7086,8 +7072,8 @@ func (_FastBridge *FastBridgeFilterer) WatchGuardRemoved(opts *bind.WatchOpts, s select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeGuardRemoved) - if err := _FastBridge.contract.UnpackLog(event, "GuardRemoved", log); err != nil { + event := new(FastBridgeRoleGranted) + if err := _FastBridge.contract.UnpackLog(event, "RoleGranted", log); err != nil { return err } event.Raw = log @@ -7108,21 +7094,21 @@ func (_FastBridge *FastBridgeFilterer) WatchGuardRemoved(opts *bind.WatchOpts, s }), nil } -// ParseGuardRemoved is a log parse operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. // -// Solidity: event GuardRemoved(address guard) -func (_FastBridge *FastBridgeFilterer) ParseGuardRemoved(log types.Log) (*FastBridgeGuardRemoved, error) { - event := new(FastBridgeGuardRemoved) - if err := _FastBridge.contract.UnpackLog(event, "GuardRemoved", log); err != nil { +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_FastBridge *FastBridgeFilterer) ParseRoleGranted(log types.Log) (*FastBridgeRoleGranted, error) { + event := new(FastBridgeRoleGranted) + if err := _FastBridge.contract.UnpackLog(event, "RoleGranted", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeRelayerAddedIterator is returned from FilterRelayerAdded and is used to iterate over the raw logs and unpacked data for RelayerAdded events raised by the FastBridge contract. -type FastBridgeRelayerAddedIterator struct { - Event *FastBridgeRelayerAdded // Event containing the contract specifics and raw log +// FastBridgeRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the FastBridge contract. +type FastBridgeRoleRevokedIterator struct { + Event *FastBridgeRoleRevoked // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -7136,7 +7122,7 @@ type FastBridgeRelayerAddedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeRelayerAddedIterator) Next() bool { +func (it *FastBridgeRoleRevokedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -7145,7 +7131,7 @@ func (it *FastBridgeRelayerAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeRelayerAdded) + it.Event = new(FastBridgeRoleRevoked) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -7160,7 +7146,7 @@ func (it *FastBridgeRelayerAddedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeRelayerAdded) + it.Event = new(FastBridgeRoleRevoked) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -7176,41 +7162,69 @@ func (it *FastBridgeRelayerAddedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeRelayerAddedIterator) Error() error { +func (it *FastBridgeRoleRevokedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeRelayerAddedIterator) Close() error { +func (it *FastBridgeRoleRevokedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeRelayerAdded represents a RelayerAdded event raised by the FastBridge contract. -type FastBridgeRelayerAdded struct { - Relayer common.Address +// FastBridgeRoleRevoked represents a RoleRevoked event raised by the FastBridge contract. +type FastBridgeRoleRevoked struct { + Role [32]byte + Account common.Address + Sender common.Address Raw types.Log // Blockchain specific contextual infos } -// FilterRelayerAdded is a free log retrieval operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. // -// Solidity: event RelayerAdded(address relayer) -func (_FastBridge *FastBridgeFilterer) FilterRelayerAdded(opts *bind.FilterOpts) (*FastBridgeRelayerAddedIterator, error) { +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_FastBridge *FastBridgeFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*FastBridgeRoleRevokedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "RelayerAdded") + logs, sub, err := _FastBridge.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) if err != nil { return nil, err } - return &FastBridgeRelayerAddedIterator{contract: _FastBridge.contract, event: "RelayerAdded", logs: logs, sub: sub}, nil + return &FastBridgeRoleRevokedIterator{contract: _FastBridge.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil } -// WatchRelayerAdded is a free log subscription operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. // -// Solidity: event RelayerAdded(address relayer) -func (_FastBridge *FastBridgeFilterer) WatchRelayerAdded(opts *bind.WatchOpts, sink chan<- *FastBridgeRelayerAdded) (event.Subscription, error) { +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_FastBridge *FastBridgeFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *FastBridgeRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "RelayerAdded") + logs, sub, err := _FastBridge.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) if err != nil { return nil, err } @@ -7220,8 +7234,8 @@ func (_FastBridge *FastBridgeFilterer) WatchRelayerAdded(opts *bind.WatchOpts, s select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeRelayerAdded) - if err := _FastBridge.contract.UnpackLog(event, "RelayerAdded", log); err != nil { + event := new(FastBridgeRoleRevoked) + if err := _FastBridge.contract.UnpackLog(event, "RoleRevoked", log); err != nil { return err } event.Raw = log @@ -7242,861 +7256,610 @@ func (_FastBridge *FastBridgeFilterer) WatchRelayerAdded(opts *bind.WatchOpts, s }), nil } -// ParseRelayerAdded is a log parse operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. // -// Solidity: event RelayerAdded(address relayer) -func (_FastBridge *FastBridgeFilterer) ParseRelayerAdded(log types.Log) (*FastBridgeRelayerAdded, error) { - event := new(FastBridgeRelayerAdded) - if err := _FastBridge.contract.UnpackLog(event, "RelayerAdded", log); err != nil { +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_FastBridge *FastBridgeFilterer) ParseRoleRevoked(log types.Log) (*FastBridgeRoleRevoked, error) { + event := new(FastBridgeRoleRevoked) + if err := _FastBridge.contract.UnpackLog(event, "RoleRevoked", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeRelayerRemovedIterator is returned from FilterRelayerRemoved and is used to iterate over the raw logs and unpacked data for RelayerRemoved events raised by the FastBridge contract. -type FastBridgeRelayerRemovedIterator struct { - Event *FastBridgeRelayerRemoved // Event containing the contract specifics and raw log +// FastBridgeMockMetaData contains all meta data concerning the FastBridgeMock contract. +var FastBridgeMockMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositRefunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"BridgeProofDisputed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"transactionHash\",\"type\":\"bytes32\"}],\"name\":\"BridgeProofProvided\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"BridgeRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"}],\"name\":\"BridgeRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REFUNDER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"structIFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"bridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionid\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"canClaim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"dispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"getBridgeTransaction\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originSender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destRecipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originFeeAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"internalType\":\"structIFastBridge.BridgeTransaction\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enumFastBridge.BridgeStatus\",\"name\":\"keyValue\",\"type\":\"uint8\"}],\"name\":\"getEnumKeyByValue\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"mockBridgeRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"structIFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"mockBridgeRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"mockBridgeRequestRaw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"destTxHash\",\"type\":\"bytes32\"}],\"name\":\"prove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"refund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "a217fddf": "DEFAULT_ADMIN_ROLE()", + "bf333f2c": "FEE_BPS()", + "0f5f6ed7": "FEE_RATE_MAX()", + "ccc57490": "GOVERNOR_ROLE()", + "03ed0ee5": "GUARD_ROLE()", + "5960ccf2": "REFUNDER_ROLE()", + "926d7d7f": "RELAYER_ROLE()", + "45851694": "bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))", + "aa9641ab": "canClaim(bytes32,address)", + "e00a83e0": "chainGasAmount()", + "41fcb612": "claim(bytes,address)", + "a3ec191a": "deployBlock()", + "add98c70": "dispute(bytes32)", + "ac11fb1a": "getBridgeTransaction(bytes)", + "85ad903d": "getEnumKeyByValue(uint8)", + "248a9ca3": "getRoleAdmin(bytes32)", + "9010d07c": "getRoleMember(bytes32,uint256)", + "ca15c873": "getRoleMemberCount(bytes32)", + "2f2ff15d": "grantRole(bytes32,address)", + "91d14854": "hasRole(bytes32,address)", + "c72870cc": "mockBridgeRelayer(bytes32,address,address,uint32,address,address,uint256,uint256,uint256)", + "acaebbf1": "mockBridgeRequest(bytes32,address,(uint32,address,address,address,address,uint256,uint256,bool,uint256))", + "aedf009d": "mockBridgeRequestRaw(bytes32,address,bytes)", + "affed0e0": "nonce()", + "58f85880": "protocolFeeRate()", + "dcf844a7": "protocolFees(address)", + "886d36ff": "prove(bytes,bytes32)", + "5eb7d946": "refund(bytes)", + "8f0d6f17": "relay(bytes)", + "36568abe": "renounceRole(bytes32,address)", + "d547741f": "revokeRole(bytes32,address)", + "b250fe6b": "setChainGasAmount(uint256)", + "b13aa2d6": "setProtocolFeeRate(uint256)", + "01ffc9a7": "supportsInterface(bytes4)", + "06f333f2": "sweepProtocolFees(address,address)", + }, + Bin: "0x60a06040523480156200001157600080fd5b506040516200254e3803806200254e833981016040819052620000349162000194565b80620000426000826200004f565b50504360805250620001bf565b6000806200005e84846200008c565b90508015620000835760008481526001602052604090206200008190846200013a565b505b90505b92915050565b6000828152602081815260408083206001600160a01b038516845290915281205460ff1662000131576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620000e83390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600162000086565b50600062000086565b600062000083836001600160a01b0384166000818152600183016020526040812054620001315750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000086565b600060208284031215620001a757600080fd5b81516001600160a01b03811681146200008357600080fd5b608051612373620001db600039600061053201526123736000f3fe6080604052600436106102345760003560e01c8063926d7d7f11610138578063b13aa2d6116100b0578063ca15c8731161007f578063d547741f11610064578063d547741f146106dd578063dcf844a7146106fd578063e00a83e01461072a57600080fd5b8063ca15c87314610689578063ccc57490146106a957600080fd5b8063b13aa2d614610612578063b250fe6b14610632578063bf333f2c14610652578063c72870cc1461066957600080fd5b8063ac11fb1a11610107578063add98c70116100ec578063add98c70146105c1578063aedf009d146105dc578063affed0e0146105fc57600080fd5b8063ac11fb1a14610574578063acaebbf1146105a157600080fd5b8063926d7d7f146104d7578063a217fddf1461050b578063a3ec191a14610520578063aa9641ab1461055457600080fd5b806345851694116101cb57806385ad903d1161019a5780638f0d6f171161017f5780638f0d6f17146104335780639010d07c1461044157806391d148541461048657600080fd5b806385ad903d146103eb578063886d36ff1461041857600080fd5b8063458516941461037857806358f85880146103865780635960ccf21461039c5780635eb7d946146103d057600080fd5b8063248a9ca311610207578063248a9ca3146102e85780632f2ff15d1461031857806336568abe1461033857806341fcb6121461035857600080fd5b806301ffc9a71461023957806303ed0ee51461026e57806306f333f2146102b05780630f5f6ed7146102d2575b600080fd5b34801561024557600080fd5b5061025961025436600461195d565b610740565b60405190151581526020015b60405180910390f35b34801561027a57600080fd5b506102a27f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b604051908152602001610265565b3480156102bc57600080fd5b506102d06102cb3660046119d1565b61079c565b005b3480156102de57600080fd5b506102a261271081565b3480156102f457600080fd5b506102a2610303366004611a0a565b60009081526020819052604090206001015490565b34801561032457600080fd5b506102d0610333366004611a23565b61088a565b34801561034457600080fd5b506102d0610353366004611a23565b6108b5565b34801561036457600080fd5b506102d0610373366004611b70565b61090e565b6102d0610373366004611c90565b34801561039257600080fd5b506102a260025481565b3480156103a857600080fd5b506102a27fdb9556138406326f00296e13ea2ad7db24ba82381212d816b1a40c23b466b32781565b3480156103dc57600080fd5b506102d0610373366004611cad565b3480156103f757600080fd5b5061040b610406366004611cea565b610975565b6040516102659190611d79565b34801561042457600080fd5b506102d0610373366004611d8c565b6102d0610373366004611cad565b34801561044d57600080fd5b5061046161045c366004611dd1565b610b25565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610265565b34801561049257600080fd5b506102596104a1366004611a23565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b3480156104e357600080fd5b506102a27fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b34801561051757600080fd5b506102a2600081565b34801561052c57600080fd5b506102a27f000000000000000000000000000000000000000000000000000000000000000081565b34801561056057600080fd5b5061025961056f366004611a23565b610b44565b34801561058057600080fd5b5061059461058f366004611cad565b610ba9565b6040516102659190611df3565b3480156105ad57600080fd5b506102d06105bc366004611f0d565b610c1c565b3480156105cd57600080fd5b506102d0610373366004611a0a565b3480156105e857600080fd5b506102d06105f7366004611f4d565b610dec565b34801561060857600080fd5b506102a260055481565b34801561061e57600080fd5b506102d061062d366004611a0a565b610e77565b34801561063e57600080fd5b506102d061064d366004611a0a565b610f54565b34801561065e57600080fd5b506102a2620f424081565b34801561067557600080fd5b506102d0610684366004611fa6565b610fbc565b34801561069557600080fd5b506102a26106a4366004611a0a565b611042565b3480156106b557600080fd5b506102a27f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b3480156106e957600080fd5b506102d06106f8366004611a23565b611059565b34801561070957600080fd5b506102a261071836600461203e565b60036020526000908152604090205481565b34801561073657600080fd5b506102a260045481565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f00000000000000000000000000000000000000000000000000000000148061079657506107968261107e565b92915050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556107c681611115565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812054908190036107fa5750505050565b73ffffffffffffffffffffffffffffffffffffffff841660008181526003602052604081205561082b908483611122565b6040805173ffffffffffffffffffffffffffffffffffffffff8087168252851660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b505050565b6000828152602081905260409020600101546108a581611115565b6108af8383611279565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610904576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61088582826112ae565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6e6f7420696d706c656d656e746564000000000000000000000000000000000060448201526064015b60405180910390fd5b60608160048111156109895761098961205b565b6000036109c957505060408051808201909152600481527f4e554c4c00000000000000000000000000000000000000000000000000000000602082015290565b8160048111156109db576109db61205b565b600103610a1b57505060408051808201909152600981527f5245515545535445440000000000000000000000000000000000000000000000602082015290565b816004811115610a2d57610a2d61205b565b600203610a6d57505060408051808201909152600e81527f52454c415945525f50524f564544000000000000000000000000000000000000602082015290565b816004811115610a7f57610a7f61205b565b600303610abf57505060408051808201909152600f81527f52454c415945525f434c41494d45440000000000000000000000000000000000602082015290565b816004811115610ad157610ad161205b565b600403610b1157505060408051808201909152600881527f524546554e444544000000000000000000000000000000000000000000000000602082015290565b505060408051602081019091526000815290565b6000828152600160205260408120610b3d90836112db565b9392505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6e6f7420696d706c656d656e7465640000000000000000000000000000000000604482015260009060640161096c565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201528251909161079691840181019084016120ab565b6000620f42406002548360a00151610c3491906121a6565b610c3e91906121bd565b9050808260a001818151610c5291906121f8565b9150818152505060006040518061018001604052804663ffffffff168152602001846000015163ffffffff168152602001846020015173ffffffffffffffffffffffffffffffffffffffff168152602001846040015173ffffffffffffffffffffffffffffffffffffffff168152602001846060015173ffffffffffffffffffffffffffffffffffffffff168152602001846080015173ffffffffffffffffffffffffffffffffffffffff1681526020018460a0015181526020018460c0015181526020018381526020018460e0015115158152602001846101000151815260200160056000815480929190610d479061220b565b909155509052604051610d5d9190602001611df3565b6040516020818303038152906040529050826020015173ffffffffffffffffffffffffffffffffffffffff16857f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a838660000151876060015188608001518960a001518a60c001518b60e00151604051610ddd9796959493929190612243565b60405180910390a35050505050565b6000610df782610ba9565b9050806040015173ffffffffffffffffffffffffffffffffffffffff16847f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a84846020015185608001518660a001518760c001518860e00151896101200151604051610e699796959493929190612243565b60405180910390a350505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55610ea181611115565b612710821115610f0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d617800000000000000000000000000000000604482015260640161096c565b600280549083905560408051828152602081018590527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a1505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55610f7e81611115565b600480549083905560408051828152602081018590527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa9101610f47565b6040805163ffffffff8816815273ffffffffffffffffffffffffffffffffffffffff878116602083015286811682840152606082018690526080820185905260a082018490529151898316928b16918c917ff8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c9181900360c00190a4505050505050505050565b6000818152600160205260408120610796906112e7565b60008281526020819052604090206001015461107481611115565b6108af83836112ae565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061079657507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610796565b61111f81336112f1565b50565b3073ffffffffffffffffffffffffffffffffffffffff83160361114457505050565b8060000361115157505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8416016112585760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146111e8576040519150601f19603f3d011682016040523d82523d6000602084013e6111ed565b606091505b50509050806108af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c656400000000000000000000000000604482015260640161096c565b61088573ffffffffffffffffffffffffffffffffffffffff8416838361137b565b6000806112868484611408565b90508015610b3d5760008481526001602052604090206112a69084611504565b509392505050565b6000806112bb8484611526565b90508015610b3d5760008481526001602052604090206112a690846115e1565b6000610b3d8383611603565b6000610796825490565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16611377576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024810183905260440161096c565b5050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261088590849061162d565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff166114fc5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561149a3390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610796565b506000610796565b6000610b3d8373ffffffffffffffffffffffffffffffffffffffff84166116c3565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16156114fc5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610796565b6000610b3d8373ffffffffffffffffffffffffffffffffffffffff841661170a565b600082600001828154811061161a5761161a6122a6565b9060005260206000200154905092915050565b600061164f73ffffffffffffffffffffffffffffffffffffffff8416836117fd565b9050805160001415801561167457508080602001905181019061167291906122d5565b155b15610885576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161096c565b60008181526001830160205260408120546114fc57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610796565b600081815260018301602052604081205480156117f357600061172e6001836121f8565b8554909150600090611742906001906121f8565b90508082146117a7576000866000018281548110611762576117626122a6565b9060005260206000200154905080876000018481548110611785576117856122a6565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806117b8576117b86122f2565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610796565b6000915050610796565b6060610b3d83836000846000808573ffffffffffffffffffffffffffffffffffffffff1684866040516118309190612321565b60006040518083038185875af1925050503d806000811461186d576040519150601f19603f3d011682016040523d82523d6000602084013e611872565b606091505b509150915061188286838361188c565b9695505050505050565b6060826118a15761189c8261191b565b610b3d565b81511580156118c5575073ffffffffffffffffffffffffffffffffffffffff84163b155b15611914576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015260240161096c565b5080610b3d565b80511561192b5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561196f57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610b3d57600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461111f57600080fd5b80356119cc8161199f565b919050565b600080604083850312156119e457600080fd5b82356119ef8161199f565b915060208301356119ff8161199f565b809150509250929050565b600060208284031215611a1c57600080fd5b5035919050565b60008060408385031215611a3657600080fd5b8235915060208301356119ff8161199f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715611a9b57611a9b611a48565b60405290565b604051610180810167ffffffffffffffff81118282101715611a9b57611a9b611a48565b600082601f830112611ad657600080fd5b813567ffffffffffffffff80821115611af157611af1611a48565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611b3757611b37611a48565b81604052838152866020858801011115611b5057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215611b8357600080fd5b823567ffffffffffffffff811115611b9a57600080fd5b611ba685828601611ac5565b92505060208301356119ff8161199f565b63ffffffff8116811461111f57600080fd5b80356119cc81611bb7565b801515811461111f57600080fd5b80356119cc81611bd4565b60006101208284031215611c0057600080fd5b611c08611a77565b9050611c1382611bc9565b8152611c21602083016119c1565b6020820152611c32604083016119c1565b6040820152611c43606083016119c1565b6060820152611c54608083016119c1565b608082015260a082013560a082015260c082013560c0820152611c7960e08301611be2565b60e082015261010080830135818301525092915050565b60006101208284031215611ca357600080fd5b610b3d8383611bed565b600060208284031215611cbf57600080fd5b813567ffffffffffffffff811115611cd657600080fd5b611ce284828501611ac5565b949350505050565b600060208284031215611cfc57600080fd5b813560058110610b3d57600080fd5b60005b83811015611d26578181015183820152602001611d0e565b50506000910152565b60008151808452611d47816020860160208601611d0b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610b3d6020830184611d2f565b60008060408385031215611d9f57600080fd5b823567ffffffffffffffff811115611db657600080fd5b611dc285828601611ac5565b95602094909401359450505050565b60008060408385031215611de457600080fd5b50508035926020909101359150565b815163ffffffff16815261018081016020830151611e19602084018263ffffffff169052565b506040830151611e41604084018273ffffffffffffffffffffffffffffffffffffffff169052565b506060830151611e69606084018273ffffffffffffffffffffffffffffffffffffffff169052565b506080830151611e91608084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060a0830151611eb960a084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c083015160c083015260e083015160e083015261010080840151818401525061012080840151611eee8285018215159052565b5050610140838101519083015261016092830151929091019190915290565b60008060006101608486031215611f2357600080fd5b833592506020840135611f358161199f565b9150611f448560408601611bed565b90509250925092565b600080600060608486031215611f6257600080fd5b833592506020840135611f748161199f565b9150604084013567ffffffffffffffff811115611f9057600080fd5b611f9c86828701611ac5565b9150509250925092565b60008060008060008060008060006101208a8c031215611fc557600080fd5b8935985060208a0135611fd78161199f565b975060408a0135611fe78161199f565b965060608a0135611ff781611bb7565b955060808a01356120078161199f565b945060a08a01356120178161199f565b8094505060c08a0135925060e08a013591506101008a013590509295985092959850929598565b60006020828403121561205057600080fd5b8135610b3d8161199f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b80516119cc81611bb7565b80516119cc8161199f565b80516119cc81611bd4565b600061018082840312156120be57600080fd5b6120c6611aa1565b6120cf8361208a565b81526120dd6020840161208a565b60208201526120ee60408401612095565b60408201526120ff60608401612095565b606082015261211060808401612095565b608082015261212160a08401612095565b60a082015260c083015160c082015260e083015160e08201526101008084015181830152506101206121548185016120a0565b908201526101408381015190820152610160928301519281019290925250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761079657610796612177565b6000826121f3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561079657610796612177565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361223c5761223c612177565b5060010190565b60e08152600061225660e083018a611d2f565b63ffffffff9890981660208301525073ffffffffffffffffffffffffffffffffffffffff9586166040820152939094166060840152608083019190915260a082015290151560c090910152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156122e757600080fd5b8151610b3d81611bd4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612333818460208701611d0b565b919091019291505056fea264697066735822122033e24b6f39317f0eea840aab6ee071e2b648a79ea7849efa62c112cddf55815d64736f6c63430008140033", +} - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data +// FastBridgeMockABI is the input ABI used to generate the binding from. +// Deprecated: Use FastBridgeMockMetaData.ABI instead. +var FastBridgeMockABI = FastBridgeMockMetaData.ABI - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} +// Deprecated: Use FastBridgeMockMetaData.Sigs instead. +// FastBridgeMockFuncSigs maps the 4-byte function signature to its string representation. +var FastBridgeMockFuncSigs = FastBridgeMockMetaData.Sigs -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *FastBridgeRelayerRemovedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(FastBridgeRelayerRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// FastBridgeMockBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use FastBridgeMockMetaData.Bin instead. +var FastBridgeMockBin = FastBridgeMockMetaData.Bin - default: - return false - } +// DeployFastBridgeMock deploys a new Ethereum contract, binding an instance of FastBridgeMock to it. +func DeployFastBridgeMock(auth *bind.TransactOpts, backend bind.ContractBackend, _owner common.Address) (common.Address, *types.Transaction, *FastBridgeMock, error) { + parsed, err := FastBridgeMockMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(FastBridgeRelayerRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(FastBridgeMockBin), backend, _owner) + if err != nil { + return common.Address{}, nil, nil, err } + return address, tx, &FastBridgeMock{FastBridgeMockCaller: FastBridgeMockCaller{contract: contract}, FastBridgeMockTransactor: FastBridgeMockTransactor{contract: contract}, FastBridgeMockFilterer: FastBridgeMockFilterer{contract: contract}}, nil } -// Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeRelayerRemovedIterator) Error() error { - return it.fail +// FastBridgeMock is an auto generated Go binding around an Ethereum contract. +type FastBridgeMock struct { + FastBridgeMockCaller // Read-only binding to the contract + FastBridgeMockTransactor // Write-only binding to the contract + FastBridgeMockFilterer // Log filterer for contract events } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *FastBridgeRelayerRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// FastBridgeMockCaller is an auto generated read-only Go binding around an Ethereum contract. +type FastBridgeMockCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// FastBridgeRelayerRemoved represents a RelayerRemoved event raised by the FastBridge contract. -type FastBridgeRelayerRemoved struct { - Relayer common.Address - Raw types.Log // Blockchain specific contextual infos +// FastBridgeMockTransactor is an auto generated write-only Go binding around an Ethereum contract. +type FastBridgeMockTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// FilterRelayerRemoved is a free log retrieval operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. -// -// Solidity: event RelayerRemoved(address relayer) -func (_FastBridge *FastBridgeFilterer) FilterRelayerRemoved(opts *bind.FilterOpts) (*FastBridgeRelayerRemovedIterator, error) { +// FastBridgeMockFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type FastBridgeMockFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// FastBridgeMockSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type FastBridgeMockSession struct { + Contract *FastBridgeMock // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// FastBridgeMockCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type FastBridgeMockCallerSession struct { + Contract *FastBridgeMockCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// FastBridgeMockTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type FastBridgeMockTransactorSession struct { + Contract *FastBridgeMockTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// FastBridgeMockRaw is an auto generated low-level Go binding around an Ethereum contract. +type FastBridgeMockRaw struct { + Contract *FastBridgeMock // Generic contract binding to access the raw methods on +} + +// FastBridgeMockCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type FastBridgeMockCallerRaw struct { + Contract *FastBridgeMockCaller // Generic read-only contract binding to access the raw methods on +} + +// FastBridgeMockTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type FastBridgeMockTransactorRaw struct { + Contract *FastBridgeMockTransactor // Generic write-only contract binding to access the raw methods on +} - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "RelayerRemoved") +// NewFastBridgeMock creates a new instance of FastBridgeMock, bound to a specific deployed contract. +func NewFastBridgeMock(address common.Address, backend bind.ContractBackend) (*FastBridgeMock, error) { + contract, err := bindFastBridgeMock(address, backend, backend, backend) if err != nil { return nil, err } - return &FastBridgeRelayerRemovedIterator{contract: _FastBridge.contract, event: "RelayerRemoved", logs: logs, sub: sub}, nil + return &FastBridgeMock{FastBridgeMockCaller: FastBridgeMockCaller{contract: contract}, FastBridgeMockTransactor: FastBridgeMockTransactor{contract: contract}, FastBridgeMockFilterer: FastBridgeMockFilterer{contract: contract}}, nil } -// WatchRelayerRemoved is a free log subscription operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. -// -// Solidity: event RelayerRemoved(address relayer) -func (_FastBridge *FastBridgeFilterer) WatchRelayerRemoved(opts *bind.WatchOpts, sink chan<- *FastBridgeRelayerRemoved) (event.Subscription, error) { - - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "RelayerRemoved") +// NewFastBridgeMockCaller creates a new read-only instance of FastBridgeMock, bound to a specific deployed contract. +func NewFastBridgeMockCaller(address common.Address, caller bind.ContractCaller) (*FastBridgeMockCaller, error) { + contract, err := bindFastBridgeMock(address, caller, nil, nil) if err != nil { return nil, err } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(FastBridgeRelayerRemoved) - if err := _FastBridge.contract.UnpackLog(event, "RelayerRemoved", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil + return &FastBridgeMockCaller{contract: contract}, nil } -// ParseRelayerRemoved is a log parse operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. -// -// Solidity: event RelayerRemoved(address relayer) -func (_FastBridge *FastBridgeFilterer) ParseRelayerRemoved(log types.Log) (*FastBridgeRelayerRemoved, error) { - event := new(FastBridgeRelayerRemoved) - if err := _FastBridge.contract.UnpackLog(event, "RelayerRemoved", log); err != nil { +// NewFastBridgeMockTransactor creates a new write-only instance of FastBridgeMock, bound to a specific deployed contract. +func NewFastBridgeMockTransactor(address common.Address, transactor bind.ContractTransactor) (*FastBridgeMockTransactor, error) { + contract, err := bindFastBridgeMock(address, nil, transactor, nil) + if err != nil { return nil, err } - event.Raw = log - return event, nil + return &FastBridgeMockTransactor{contract: contract}, nil } -// FastBridgeRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the FastBridge contract. -type FastBridgeRoleAdminChangedIterator struct { - Event *FastBridgeRoleAdminChanged // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// NewFastBridgeMockFilterer creates a new log filterer instance of FastBridgeMock, bound to a specific deployed contract. +func NewFastBridgeMockFilterer(address common.Address, filterer bind.ContractFilterer) (*FastBridgeMockFilterer, error) { + contract, err := bindFastBridgeMock(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &FastBridgeMockFilterer{contract: contract}, nil } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *FastBridgeRoleAdminChangedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false +// bindFastBridgeMock binds a generic wrapper to an already deployed contract. +func bindFastBridgeMock(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := FastBridgeMockMetaData.GetAbi() + if err != nil { + return nil, err } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(FastBridgeRoleAdminChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(FastBridgeRoleAdminChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_FastBridgeMock *FastBridgeMockRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _FastBridgeMock.Contract.FastBridgeMockCaller.contract.Call(opts, result, method, params...) +} - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_FastBridgeMock *FastBridgeMockRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _FastBridgeMock.Contract.FastBridgeMockTransactor.contract.Transfer(opts) } -// Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeRoleAdminChangedIterator) Error() error { - return it.fail +// Transact invokes the (paid) contract method with params as input values. +func (_FastBridgeMock *FastBridgeMockRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _FastBridgeMock.Contract.FastBridgeMockTransactor.contract.Transact(opts, method, params...) } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *FastBridgeRoleAdminChangedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_FastBridgeMock *FastBridgeMockCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _FastBridgeMock.Contract.contract.Call(opts, result, method, params...) } -// FastBridgeRoleAdminChanged represents a RoleAdminChanged event raised by the FastBridge contract. -type FastBridgeRoleAdminChanged struct { - Role [32]byte - PreviousAdminRole [32]byte - NewAdminRole [32]byte - Raw types.Log // Blockchain specific contextual infos +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_FastBridgeMock *FastBridgeMockTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _FastBridgeMock.Contract.contract.Transfer(opts) } -// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// Transact invokes the (paid) contract method with params as input values. +func (_FastBridgeMock *FastBridgeMockTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _FastBridgeMock.Contract.contract.Transact(opts, method, params...) +} + +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. // -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_FastBridge *FastBridgeFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*FastBridgeRoleAdminChangedIterator, error) { +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_FastBridgeMock *FastBridgeMockCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _FastBridgeMock.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var previousAdminRoleRule []interface{} - for _, previousAdminRoleItem := range previousAdminRole { - previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) - } - var newAdminRoleRule []interface{} - for _, newAdminRoleItem := range newAdminRole { - newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + if err != nil { + return *new([32]byte), err } - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) - if err != nil { - return nil, err - } - return &FastBridgeRoleAdminChangedIterator{contract: _FastBridge.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. // -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_FastBridge *FastBridgeFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *FastBridgeRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_FastBridgeMock *FastBridgeMockSession) DEFAULTADMINROLE() ([32]byte, error) { + return _FastBridgeMock.Contract.DEFAULTADMINROLE(&_FastBridgeMock.CallOpts) +} - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var previousAdminRoleRule []interface{} - for _, previousAdminRoleItem := range previousAdminRole { - previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) - } - var newAdminRoleRule []interface{} - for _, newAdminRoleItem := range newAdminRole { - newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) - } +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_FastBridgeMock *FastBridgeMockCallerSession) DEFAULTADMINROLE() ([32]byte, error) { + return _FastBridgeMock.Contract.DEFAULTADMINROLE(&_FastBridgeMock.CallOpts) +} + +// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. +// +// Solidity: function FEE_BPS() view returns(uint256) +func (_FastBridgeMock *FastBridgeMockCaller) FEEBPS(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FastBridgeMock.contract.Call(opts, &out, "FEE_BPS") - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { - return nil, err + return *new(*big.Int), err } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(FastBridgeRoleAdminChanged) - if err := _FastBridge.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { - return err - } - event.Raw = log - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. // -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_FastBridge *FastBridgeFilterer) ParseRoleAdminChanged(log types.Log) (*FastBridgeRoleAdminChanged, error) { - event := new(FastBridgeRoleAdminChanged) - if err := _FastBridge.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function FEE_BPS() view returns(uint256) +func (_FastBridgeMock *FastBridgeMockSession) FEEBPS() (*big.Int, error) { + return _FastBridgeMock.Contract.FEEBPS(&_FastBridgeMock.CallOpts) } -// FastBridgeRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the FastBridge contract. -type FastBridgeRoleGrantedIterator struct { - Event *FastBridgeRoleGranted // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. +// +// Solidity: function FEE_BPS() view returns(uint256) +func (_FastBridgeMock *FastBridgeMockCallerSession) FEEBPS() (*big.Int, error) { + return _FastBridgeMock.Contract.FEEBPS(&_FastBridgeMock.CallOpts) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *FastBridgeRoleGrantedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(FastBridgeRoleGranted) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. +// +// Solidity: function FEE_RATE_MAX() view returns(uint256) +func (_FastBridgeMock *FastBridgeMockCaller) FEERATEMAX(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FastBridgeMock.contract.Call(opts, &out, "FEE_RATE_MAX") - default: - return false - } + if err != nil { + return *new(*big.Int), err } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(FastBridgeRoleGranted) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) -// Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeRoleGrantedIterator) Error() error { - return it.fail -} + return out0, err -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *FastBridgeRoleGrantedIterator) Close() error { - it.sub.Unsubscribe() - return nil } -// FastBridgeRoleGranted represents a RoleGranted event raised by the FastBridge contract. -type FastBridgeRoleGranted struct { - Role [32]byte - Account common.Address - Sender common.Address - Raw types.Log // Blockchain specific contextual infos +// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. +// +// Solidity: function FEE_RATE_MAX() view returns(uint256) +func (_FastBridgeMock *FastBridgeMockSession) FEERATEMAX() (*big.Int, error) { + return _FastBridgeMock.Contract.FEERATEMAX(&_FastBridgeMock.CallOpts) } -// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. // -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_FastBridge *FastBridgeFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*FastBridgeRoleGrantedIterator, error) { +// Solidity: function FEE_RATE_MAX() view returns(uint256) +func (_FastBridgeMock *FastBridgeMockCallerSession) FEERATEMAX() (*big.Int, error) { + return _FastBridgeMock.Contract.FEERATEMAX(&_FastBridgeMock.CallOpts) +} - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } +// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. +// +// Solidity: function GOVERNOR_ROLE() view returns(bytes32) +func (_FastBridgeMock *FastBridgeMockCaller) GOVERNORROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _FastBridgeMock.contract.Call(opts, &out, "GOVERNOR_ROLE") - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) if err != nil { - return nil, err + return *new([32]byte), err } - return &FastBridgeRoleGrantedIterator{contract: _FastBridge.contract, event: "RoleGranted", logs: logs, sub: sub}, nil + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. // -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_FastBridge *FastBridgeFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *FastBridgeRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { +// Solidity: function GOVERNOR_ROLE() view returns(bytes32) +func (_FastBridgeMock *FastBridgeMockSession) GOVERNORROLE() ([32]byte, error) { + return _FastBridgeMock.Contract.GOVERNORROLE(&_FastBridgeMock.CallOpts) +} - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } +// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. +// +// Solidity: function GOVERNOR_ROLE() view returns(bytes32) +func (_FastBridgeMock *FastBridgeMockCallerSession) GOVERNORROLE() ([32]byte, error) { + return _FastBridgeMock.Contract.GOVERNORROLE(&_FastBridgeMock.CallOpts) +} + +// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. +// +// Solidity: function GUARD_ROLE() view returns(bytes32) +func (_FastBridgeMock *FastBridgeMockCaller) GUARDROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _FastBridgeMock.contract.Call(opts, &out, "GUARD_ROLE") - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) if err != nil { - return nil, err + return *new([32]byte), err } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(FastBridgeRoleGranted) - if err := _FastBridge.contract.UnpackLog(event, "RoleGranted", log); err != nil { - return err - } - event.Raw = log - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. // -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_FastBridge *FastBridgeFilterer) ParseRoleGranted(log types.Log) (*FastBridgeRoleGranted, error) { - event := new(FastBridgeRoleGranted) - if err := _FastBridge.contract.UnpackLog(event, "RoleGranted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function GUARD_ROLE() view returns(bytes32) +func (_FastBridgeMock *FastBridgeMockSession) GUARDROLE() ([32]byte, error) { + return _FastBridgeMock.Contract.GUARDROLE(&_FastBridgeMock.CallOpts) } -// FastBridgeRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the FastBridge contract. -type FastBridgeRoleRevokedIterator struct { - Event *FastBridgeRoleRevoked // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. +// +// Solidity: function GUARD_ROLE() view returns(bytes32) +func (_FastBridgeMock *FastBridgeMockCallerSession) GUARDROLE() ([32]byte, error) { + return _FastBridgeMock.Contract.GUARDROLE(&_FastBridgeMock.CallOpts) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *FastBridgeRoleRevokedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(FastBridgeRoleRevoked) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// REFUNDERROLE is a free data retrieval call binding the contract method 0x5960ccf2. +// +// Solidity: function REFUNDER_ROLE() view returns(bytes32) +func (_FastBridgeMock *FastBridgeMockCaller) REFUNDERROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _FastBridgeMock.contract.Call(opts, &out, "REFUNDER_ROLE") - default: - return false - } + if err != nil { + return *new([32]byte), err } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(FastBridgeRoleRevoked) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) -// Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeRoleRevokedIterator) Error() error { - return it.fail -} + return out0, err -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *FastBridgeRoleRevokedIterator) Close() error { - it.sub.Unsubscribe() - return nil } -// FastBridgeRoleRevoked represents a RoleRevoked event raised by the FastBridge contract. -type FastBridgeRoleRevoked struct { - Role [32]byte - Account common.Address - Sender common.Address - Raw types.Log // Blockchain specific contextual infos +// REFUNDERROLE is a free data retrieval call binding the contract method 0x5960ccf2. +// +// Solidity: function REFUNDER_ROLE() view returns(bytes32) +func (_FastBridgeMock *FastBridgeMockSession) REFUNDERROLE() ([32]byte, error) { + return _FastBridgeMock.Contract.REFUNDERROLE(&_FastBridgeMock.CallOpts) } -// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// REFUNDERROLE is a free data retrieval call binding the contract method 0x5960ccf2. // -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_FastBridge *FastBridgeFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*FastBridgeRoleRevokedIterator, error) { +// Solidity: function REFUNDER_ROLE() view returns(bytes32) +func (_FastBridgeMock *FastBridgeMockCallerSession) REFUNDERROLE() ([32]byte, error) { + return _FastBridgeMock.Contract.REFUNDERROLE(&_FastBridgeMock.CallOpts) +} - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } +// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. +// +// Solidity: function RELAYER_ROLE() view returns(bytes32) +func (_FastBridgeMock *FastBridgeMockCaller) RELAYERROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _FastBridgeMock.contract.Call(opts, &out, "RELAYER_ROLE") - logs, sub, err := _FastBridge.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) if err != nil { - return nil, err + return *new([32]byte), err } - return &FastBridgeRoleRevokedIterator{contract: _FastBridge.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. // -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_FastBridge *FastBridgeFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *FastBridgeRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { +// Solidity: function RELAYER_ROLE() view returns(bytes32) +func (_FastBridgeMock *FastBridgeMockSession) RELAYERROLE() ([32]byte, error) { + return _FastBridgeMock.Contract.RELAYERROLE(&_FastBridgeMock.CallOpts) +} - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } +// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. +// +// Solidity: function RELAYER_ROLE() view returns(bytes32) +func (_FastBridgeMock *FastBridgeMockCallerSession) RELAYERROLE() ([32]byte, error) { + return _FastBridgeMock.Contract.RELAYERROLE(&_FastBridgeMock.CallOpts) +} + +// CanClaim is a free data retrieval call binding the contract method 0xaa9641ab. +// +// Solidity: function canClaim(bytes32 transactionid, address relayer) view returns(bool) +func (_FastBridgeMock *FastBridgeMockCaller) CanClaim(opts *bind.CallOpts, transactionid [32]byte, relayer common.Address) (bool, error) { + var out []interface{} + err := _FastBridgeMock.contract.Call(opts, &out, "canClaim", transactionid, relayer) - logs, sub, err := _FastBridge.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) if err != nil { - return nil, err + return *new(bool), err } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(FastBridgeRoleRevoked) - if err := _FastBridge.contract.UnpackLog(event, "RoleRevoked", log); err != nil { - return err - } - event.Raw = log - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + } -// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// CanClaim is a free data retrieval call binding the contract method 0xaa9641ab. // -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_FastBridge *FastBridgeFilterer) ParseRoleRevoked(log types.Log) (*FastBridgeRoleRevoked, error) { - event := new(FastBridgeRoleRevoked) - if err := _FastBridge.contract.UnpackLog(event, "RoleRevoked", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function canClaim(bytes32 transactionid, address relayer) view returns(bool) +func (_FastBridgeMock *FastBridgeMockSession) CanClaim(transactionid [32]byte, relayer common.Address) (bool, error) { + return _FastBridgeMock.Contract.CanClaim(&_FastBridgeMock.CallOpts, transactionid, relayer) } -// FastBridgeMockMetaData contains all meta data concerning the FastBridgeMock contract. -var FastBridgeMockMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositRefunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"BridgeProofDisputed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"transactionHash\",\"type\":\"bytes32\"}],\"name\":\"BridgeProofProvided\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"BridgeRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"}],\"name\":\"BridgeRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"addGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"addGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"addRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"structIFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"bridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionid\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"canClaim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"dispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"getBridgeTransaction\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originSender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destRecipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originFeeAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"internalType\":\"structIFastBridge.BridgeTransaction\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enumFastBridge.BridgeStatus\",\"name\":\"keyValue\",\"type\":\"uint8\"}],\"name\":\"getEnumKeyByValue\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"mockBridgeRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"structIFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"mockBridgeRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"mockBridgeRequestRaw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"destTxHash\",\"type\":\"bytes32\"}],\"name\":\"prove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"refund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"removeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"removeGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"removeRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Sigs: map[string]string{ - "a217fddf": "DEFAULT_ADMIN_ROLE()", - "bf333f2c": "FEE_BPS()", - "0f5f6ed7": "FEE_RATE_MAX()", - "ccc57490": "GOVERNOR_ROLE()", - "03ed0ee5": "GUARD_ROLE()", - "926d7d7f": "RELAYER_ROLE()", - "3c4a25d0": "addGovernor(address)", - "6913a63c": "addGuard(address)", - "dd39f00d": "addRelayer(address)", - "45851694": "bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))", - "aa9641ab": "canClaim(bytes32,address)", - "e00a83e0": "chainGasAmount()", - "41fcb612": "claim(bytes,address)", - "a3ec191a": "deployBlock()", - "add98c70": "dispute(bytes32)", - "ac11fb1a": "getBridgeTransaction(bytes)", - "85ad903d": "getEnumKeyByValue(uint8)", - "248a9ca3": "getRoleAdmin(bytes32)", - "2f2ff15d": "grantRole(bytes32,address)", - "91d14854": "hasRole(bytes32,address)", - "c72870cc": "mockBridgeRelayer(bytes32,address,address,uint32,address,address,uint256,uint256,uint256)", - "acaebbf1": "mockBridgeRequest(bytes32,address,(uint32,address,address,address,address,uint256,uint256,bool,uint256))", - "aedf009d": "mockBridgeRequestRaw(bytes32,address,bytes)", - "affed0e0": "nonce()", - "58f85880": "protocolFeeRate()", - "dcf844a7": "protocolFees(address)", - "886d36ff": "prove(bytes,bytes32)", - "5eb7d946": "refund(bytes)", - "8f0d6f17": "relay(bytes)", - "eecdac88": "removeGovernor(address)", - "b6235016": "removeGuard(address)", - "60f0a5ac": "removeRelayer(address)", - "36568abe": "renounceRole(bytes32,address)", - "d547741f": "revokeRole(bytes32,address)", - "b250fe6b": "setChainGasAmount(uint256)", - "b13aa2d6": "setProtocolFeeRate(uint256)", - "01ffc9a7": "supportsInterface(bytes4)", - "06f333f2": "sweepProtocolFees(address,address)", - }, - Bin: "0x60a06040523480156200001157600080fd5b50604051620027a7380380620027a78339810160408190526200003491620000fe565b80620000426000826200004f565b5050436080525062000130565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16620000f4576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620000ab3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001620000f8565b5060005b92915050565b6000602082840312156200011157600080fd5b81516001600160a01b03811681146200012957600080fd5b9392505050565b60805161265b6200014c600039600061056a015261265b6000f3fe6080604052600436106102855760003560e01c8063a217fddf11610153578063b250fe6b116100cb578063d547741f1161007f578063dd39f00d11610064578063dd39f00d14610762578063e00a83e014610782578063eecdac881461079857600080fd5b8063d547741f14610715578063dcf844a71461073557600080fd5b8063bf333f2c116100b0578063bf333f2c146106aa578063c72870cc146106c1578063ccc57490146106e157600080fd5b8063b250fe6b1461066a578063b62350161461068a57600080fd5b8063acaebbf111610122578063aedf009d11610107578063aedf009d14610614578063affed0e014610634578063b13aa2d61461064a57600080fd5b8063acaebbf1146105d9578063add98c70146105f957600080fd5b8063a217fddf14610543578063a3ec191a14610558578063aa9641ab1461058c578063ac11fb1a146105ac57600080fd5b8063458516941161020157806385ad903d116101b55780638f0d6f171161019a5780638f0d6f17146104b057806391d14854146104be578063926d7d7f1461050f57600080fd5b806385ad903d14610468578063886d36ff1461049557600080fd5b80635eb7d946116101e65780635eb7d9461461040d57806360f0a5ac146104285780636913a63c1461044857600080fd5b806345851694146103e957806358f85880146103f757600080fd5b8063248a9ca31161025857806336568abe1161023d57806336568abe146103895780633c4a25d0146103a957806341fcb612146103c957600080fd5b8063248a9ca3146103395780632f2ff15d1461036957600080fd5b806301ffc9a71461028a57806303ed0ee5146102bf57806306f333f2146103015780630f5f6ed714610323575b600080fd5b34801561029657600080fd5b506102aa6102a5366004611cc5565b6107b8565b60405190151581526020015b60405180910390f35b3480156102cb57600080fd5b506102f37f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b6040519081526020016102b6565b34801561030d57600080fd5b5061032161031c366004611d39565b610851565b005b34801561032f57600080fd5b506102f361271081565b34801561034557600080fd5b506102f3610354366004611d72565b60009081526020819052604090206001015490565b34801561037557600080fd5b50610321610384366004611d8b565b6109b0565b34801561039557600080fd5b506103216103a4366004611d8b565b6109db565b3480156103b557600080fd5b506103216103c4366004611db0565b610a39565b3480156103d557600080fd5b506103216103e4366004611ef5565b610aec565b6103216103e4366004612015565b34801561040357600080fd5b506102f360015481565b34801561041957600080fd5b506103216103e4366004612032565b34801561043457600080fd5b50610321610443366004611db0565b610b4e565b34801561045457600080fd5b50610321610463366004611db0565b610bfa565b34801561047457600080fd5b5061048861048336600461206f565b610ca6565b6040516102b691906120fe565b3480156104a157600080fd5b506103216103e4366004612111565b6103216103e4366004612032565b3480156104ca57600080fd5b506102aa6104d9366004611d8b565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561051b57600080fd5b506102f37fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b34801561054f57600080fd5b506102f3600081565b34801561056457600080fd5b506102f37f000000000000000000000000000000000000000000000000000000000000000081565b34801561059857600080fd5b506102aa6105a7366004611d8b565b610e56565b3480156105b857600080fd5b506105cc6105c7366004612032565b610ebb565b6040516102b69190612156565b3480156105e557600080fd5b506103216105f4366004612270565b610f2e565b34801561060557600080fd5b506103216103e4366004611d72565b34801561062057600080fd5b5061032161062f3660046122b0565b6110fe565b34801561064057600080fd5b506102f360045481565b34801561065657600080fd5b50610321610665366004611d72565b611189565b34801561067657600080fd5b50610321610685366004611d72565b6112d3565b34801561069657600080fd5b506103216106a5366004611db0565b6113a9565b3480156106b657600080fd5b506102f3620f424081565b3480156106cd57600080fd5b506103216106dc366004612309565b611455565b3480156106ed57600080fd5b506102f37f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b34801561072157600080fd5b50610321610730366004611d8b565b6114db565b34801561074157600080fd5b506102f3610750366004611db0565b60026020526000908152604090205481565b34801561076e57600080fd5b5061032161077d366004611db0565b611500565b34801561078e57600080fd5b506102f360035481565b3480156107a457600080fd5b506103216107b3366004611db0565b6115ac565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061084b57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff166108ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600260205260408120549081900361092157505050565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260026020526040812055610952908383611658565b6040805173ffffffffffffffffffffffffffffffffffffffff8086168252841660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b5050565b6000828152602081905260409020600101546109cb816117af565b6109d583836117bc565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610a2a576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a3482826118b8565b505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610a7457600080fd5b610a9e7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55826117bc565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5906020015b60405180910390a150565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6e6f7420696d706c656d656e746564000000000000000000000000000000000060448201526064016108e5565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610b8957600080fd5b610bb37fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4826118b8565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b90602001610ae1565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610c3557600080fd5b610c5f7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d826117bc565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f5990602001610ae1565b6060816004811115610cba57610cba6123a1565b600003610cfa57505060408051808201909152600481527f4e554c4c00000000000000000000000000000000000000000000000000000000602082015290565b816004811115610d0c57610d0c6123a1565b600103610d4c57505060408051808201909152600981527f5245515545535445440000000000000000000000000000000000000000000000602082015290565b816004811115610d5e57610d5e6123a1565b600203610d9e57505060408051808201909152600e81527f52454c415945525f50524f564544000000000000000000000000000000000000602082015290565b816004811115610db057610db06123a1565b600303610df057505060408051808201909152600f81527f52454c415945525f434c41494d45440000000000000000000000000000000000602082015290565b816004811115610e0257610e026123a1565b600403610e4257505060408051808201909152600881527f524546554e444544000000000000000000000000000000000000000000000000602082015290565b505060408051602081019091526000815290565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6e6f7420696d706c656d656e746564000000000000000000000000000000000060448201526000906064016108e5565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201528251909161084b91840181019084016123f1565b6000620f42406001548360a00151610f4691906124ec565b610f509190612503565b9050808260a001818151610f64919061253e565b9150818152505060006040518061018001604052804663ffffffff168152602001846000015163ffffffff168152602001846020015173ffffffffffffffffffffffffffffffffffffffff168152602001846040015173ffffffffffffffffffffffffffffffffffffffff168152602001846060015173ffffffffffffffffffffffffffffffffffffffff168152602001846080015173ffffffffffffffffffffffffffffffffffffffff1681526020018460a0015181526020018460c0015181526020018381526020018460e001511515815260200184610100015181526020016004600081548092919061105990612551565b90915550905260405161106f9190602001612156565b6040516020818303038152906040529050826020015173ffffffffffffffffffffffffffffffffffffffff16857f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a838660000151876060015188608001518960a001518a60c001518b60e001516040516110ef9796959493929190612589565b60405180910390a35050505050565b600061110982610ebb565b9050806040015173ffffffffffffffffffffffffffffffffffffffff16847f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a84846020015185608001518660a001518760c001518860e0015189610120015160405161117b9796959493929190612589565b60405180910390a350505050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16611221576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064016108e5565b61271081111561128d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064016108e5565b600180549082905560408051828152602081018490527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a15050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff1661136b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064016108e5565b600380549082905560408051828152602081018490527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa91016112c7565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166113e457600080fd5b61140e7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d826118b8565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d04890602001610ae1565b6040805163ffffffff8816815273ffffffffffffffffffffffffffffffffffffffff878116602083015286811682840152606082018690526080820185905260a082018490529151898316928b16918c917ff8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c9181900360c00190a4505050505050505050565b6000828152602081905260409020600101546114f6816117af565b6109d583836118b8565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661153b57600080fd5b6115657fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4826117bc565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c590602001610ae1565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166115e757600080fd5b6116117f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55826118b8565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b90602001610ae1565b3073ffffffffffffffffffffffffffffffffffffffff83160361167a57505050565b8060000361168757505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff84160161178e5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461171e576040519150601f19603f3d011682016040523d82523d6000602084013e611723565b606091505b50509050806109d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c65640000000000000000000000000060448201526064016108e5565b610a3473ffffffffffffffffffffffffffffffffffffffff84168383611973565b6117b98133611a00565b50565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff166118b05760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561184e3390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161084b565b50600061084b565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16156118b05760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161084b565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a34908490611a86565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109ac576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602481018390526044016108e5565b6000611aa873ffffffffffffffffffffffffffffffffffffffff841683611b1c565b90508051600014158015611acd575080806020019051810190611acb91906125ec565b155b15610a34576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016108e5565b6060611b2a83836000611b31565b9392505050565b606081471015611b6f576040517fcd7860590000000000000000000000000000000000000000000000000000000081523060048201526024016108e5565b6000808573ffffffffffffffffffffffffffffffffffffffff168486604051611b989190612609565b60006040518083038185875af1925050503d8060008114611bd5576040519150601f19603f3d011682016040523d82523d6000602084013e611bda565b606091505b5091509150611bea868383611bf4565b9695505050505050565b606082611c0957611c0482611c83565b611b2a565b8151158015611c2d575073ffffffffffffffffffffffffffffffffffffffff84163b155b15611c7c576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016108e5565b5080611b2a565b805115611c935780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060208284031215611cd757600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611b2a57600080fd5b73ffffffffffffffffffffffffffffffffffffffff811681146117b957600080fd5b8035611d3481611d07565b919050565b60008060408385031215611d4c57600080fd5b8235611d5781611d07565b91506020830135611d6781611d07565b809150509250929050565b600060208284031215611d8457600080fd5b5035919050565b60008060408385031215611d9e57600080fd5b823591506020830135611d6781611d07565b600060208284031215611dc257600080fd5b8135611b2a81611d07565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715611e2057611e20611dcd565b60405290565b604051610180810167ffffffffffffffff81118282101715611e2057611e20611dcd565b600082601f830112611e5b57600080fd5b813567ffffffffffffffff80821115611e7657611e76611dcd565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611ebc57611ebc611dcd565b81604052838152866020858801011115611ed557600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215611f0857600080fd5b823567ffffffffffffffff811115611f1f57600080fd5b611f2b85828601611e4a565b9250506020830135611d6781611d07565b63ffffffff811681146117b957600080fd5b8035611d3481611f3c565b80151581146117b957600080fd5b8035611d3481611f59565b60006101208284031215611f8557600080fd5b611f8d611dfc565b9050611f9882611f4e565b8152611fa660208301611d29565b6020820152611fb760408301611d29565b6040820152611fc860608301611d29565b6060820152611fd960808301611d29565b608082015260a082013560a082015260c082013560c0820152611ffe60e08301611f67565b60e082015261010080830135818301525092915050565b6000610120828403121561202857600080fd5b611b2a8383611f72565b60006020828403121561204457600080fd5b813567ffffffffffffffff81111561205b57600080fd5b61206784828501611e4a565b949350505050565b60006020828403121561208157600080fd5b813560058110611b2a57600080fd5b60005b838110156120ab578181015183820152602001612093565b50506000910152565b600081518084526120cc816020860160208601612090565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611b2a60208301846120b4565b6000806040838503121561212457600080fd5b823567ffffffffffffffff81111561213b57600080fd5b61214785828601611e4a565b95602094909401359450505050565b815163ffffffff1681526101808101602083015161217c602084018263ffffffff169052565b5060408301516121a4604084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060608301516121cc606084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060808301516121f4608084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060a083015161221c60a084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c083015160c083015260e083015160e0830152610100808401518184015250610120808401516122518285018215159052565b5050610140838101519083015261016092830151929091019190915290565b6000806000610160848603121561228657600080fd5b83359250602084013561229881611d07565b91506122a78560408601611f72565b90509250925092565b6000806000606084860312156122c557600080fd5b8335925060208401356122d781611d07565b9150604084013567ffffffffffffffff8111156122f357600080fd5b6122ff86828701611e4a565b9150509250925092565b60008060008060008060008060006101208a8c03121561232857600080fd5b8935985060208a013561233a81611d07565b975060408a013561234a81611d07565b965060608a013561235a81611f3c565b955060808a013561236a81611d07565b945060a08a013561237a81611d07565b8094505060c08a0135925060e08a013591506101008a013590509295985092959850929598565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8051611d3481611f3c565b8051611d3481611d07565b8051611d3481611f59565b6000610180828403121561240457600080fd5b61240c611e26565b612415836123d0565b8152612423602084016123d0565b6020820152612434604084016123db565b6040820152612445606084016123db565b6060820152612456608084016123db565b608082015261246760a084016123db565b60a082015260c083015160c082015260e083015160e082015261010080840151818301525061012061249a8185016123e6565b908201526101408381015190820152610160928301519281019290925250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761084b5761084b6124bd565b600082612539577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561084b5761084b6124bd565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612582576125826124bd565b5060010190565b60e08152600061259c60e083018a6120b4565b63ffffffff9890981660208301525073ffffffffffffffffffffffffffffffffffffffff9586166040820152939094166060840152608083019190915260a082015290151560c090910152919050565b6000602082840312156125fe57600080fd5b8151611b2a81611f59565b6000825161261b818460208701612090565b919091019291505056fea26469706673582212202542a86ea1af268a7f612e2c83128fb706733cc2fea925df68bbd0f008d32b6a64736f6c63430008140033", +// CanClaim is a free data retrieval call binding the contract method 0xaa9641ab. +// +// Solidity: function canClaim(bytes32 transactionid, address relayer) view returns(bool) +func (_FastBridgeMock *FastBridgeMockCallerSession) CanClaim(transactionid [32]byte, relayer common.Address) (bool, error) { + return _FastBridgeMock.Contract.CanClaim(&_FastBridgeMock.CallOpts, transactionid, relayer) } -// FastBridgeMockABI is the input ABI used to generate the binding from. -// Deprecated: Use FastBridgeMockMetaData.ABI instead. -var FastBridgeMockABI = FastBridgeMockMetaData.ABI - -// Deprecated: Use FastBridgeMockMetaData.Sigs instead. -// FastBridgeMockFuncSigs maps the 4-byte function signature to its string representation. -var FastBridgeMockFuncSigs = FastBridgeMockMetaData.Sigs - -// FastBridgeMockBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use FastBridgeMockMetaData.Bin instead. -var FastBridgeMockBin = FastBridgeMockMetaData.Bin +// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. +// +// Solidity: function chainGasAmount() view returns(uint256) +func (_FastBridgeMock *FastBridgeMockCaller) ChainGasAmount(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FastBridgeMock.contract.Call(opts, &out, "chainGasAmount") -// DeployFastBridgeMock deploys a new Ethereum contract, binding an instance of FastBridgeMock to it. -func DeployFastBridgeMock(auth *bind.TransactOpts, backend bind.ContractBackend, _owner common.Address) (common.Address, *types.Transaction, *FastBridgeMock, error) { - parsed, err := FastBridgeMockMetaData.GetAbi() if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") + return *new(*big.Int), err } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(FastBridgeMockBin), backend, _owner) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &FastBridgeMock{FastBridgeMockCaller: FastBridgeMockCaller{contract: contract}, FastBridgeMockTransactor: FastBridgeMockTransactor{contract: contract}, FastBridgeMockFilterer: FastBridgeMockFilterer{contract: contract}}, nil -} + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) -// FastBridgeMock is an auto generated Go binding around an Ethereum contract. -type FastBridgeMock struct { - FastBridgeMockCaller // Read-only binding to the contract - FastBridgeMockTransactor // Write-only binding to the contract - FastBridgeMockFilterer // Log filterer for contract events -} + return out0, err -// FastBridgeMockCaller is an auto generated read-only Go binding around an Ethereum contract. -type FastBridgeMockCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// FastBridgeMockTransactor is an auto generated write-only Go binding around an Ethereum contract. -type FastBridgeMockTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls +// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. +// +// Solidity: function chainGasAmount() view returns(uint256) +func (_FastBridgeMock *FastBridgeMockSession) ChainGasAmount() (*big.Int, error) { + return _FastBridgeMock.Contract.ChainGasAmount(&_FastBridgeMock.CallOpts) } -// FastBridgeMockFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type FastBridgeMockFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls +// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. +// +// Solidity: function chainGasAmount() view returns(uint256) +func (_FastBridgeMock *FastBridgeMockCallerSession) ChainGasAmount() (*big.Int, error) { + return _FastBridgeMock.Contract.ChainGasAmount(&_FastBridgeMock.CallOpts) } -// FastBridgeMockSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type FastBridgeMockSession struct { - Contract *FastBridgeMock // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} +// DeployBlock is a free data retrieval call binding the contract method 0xa3ec191a. +// +// Solidity: function deployBlock() view returns(uint256) +func (_FastBridgeMock *FastBridgeMockCaller) DeployBlock(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FastBridgeMock.contract.Call(opts, &out, "deployBlock") -// FastBridgeMockCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type FastBridgeMockCallerSession struct { - Contract *FastBridgeMockCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} + if err != nil { + return *new(*big.Int), err + } -// FastBridgeMockTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type FastBridgeMockTransactorSession struct { - Contract *FastBridgeMockTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) -// FastBridgeMockRaw is an auto generated low-level Go binding around an Ethereum contract. -type FastBridgeMockRaw struct { - Contract *FastBridgeMock // Generic contract binding to access the raw methods on -} + return out0, err -// FastBridgeMockCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type FastBridgeMockCallerRaw struct { - Contract *FastBridgeMockCaller // Generic read-only contract binding to access the raw methods on } -// FastBridgeMockTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type FastBridgeMockTransactorRaw struct { - Contract *FastBridgeMockTransactor // Generic write-only contract binding to access the raw methods on +// DeployBlock is a free data retrieval call binding the contract method 0xa3ec191a. +// +// Solidity: function deployBlock() view returns(uint256) +func (_FastBridgeMock *FastBridgeMockSession) DeployBlock() (*big.Int, error) { + return _FastBridgeMock.Contract.DeployBlock(&_FastBridgeMock.CallOpts) } -// NewFastBridgeMock creates a new instance of FastBridgeMock, bound to a specific deployed contract. -func NewFastBridgeMock(address common.Address, backend bind.ContractBackend) (*FastBridgeMock, error) { - contract, err := bindFastBridgeMock(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &FastBridgeMock{FastBridgeMockCaller: FastBridgeMockCaller{contract: contract}, FastBridgeMockTransactor: FastBridgeMockTransactor{contract: contract}, FastBridgeMockFilterer: FastBridgeMockFilterer{contract: contract}}, nil +// DeployBlock is a free data retrieval call binding the contract method 0xa3ec191a. +// +// Solidity: function deployBlock() view returns(uint256) +func (_FastBridgeMock *FastBridgeMockCallerSession) DeployBlock() (*big.Int, error) { + return _FastBridgeMock.Contract.DeployBlock(&_FastBridgeMock.CallOpts) } -// NewFastBridgeMockCaller creates a new read-only instance of FastBridgeMock, bound to a specific deployed contract. -func NewFastBridgeMockCaller(address common.Address, caller bind.ContractCaller) (*FastBridgeMockCaller, error) { - contract, err := bindFastBridgeMock(address, caller, nil, nil) +// GetBridgeTransaction is a free data retrieval call binding the contract method 0xac11fb1a. +// +// Solidity: function getBridgeTransaction(bytes request) pure returns((uint32,uint32,address,address,address,address,uint256,uint256,uint256,bool,uint256,uint256)) +func (_FastBridgeMock *FastBridgeMockCaller) GetBridgeTransaction(opts *bind.CallOpts, request []byte) (IFastBridgeBridgeTransaction, error) { + var out []interface{} + err := _FastBridgeMock.contract.Call(opts, &out, "getBridgeTransaction", request) + if err != nil { - return nil, err + return *new(IFastBridgeBridgeTransaction), err } - return &FastBridgeMockCaller{contract: contract}, nil + + out0 := *abi.ConvertType(out[0], new(IFastBridgeBridgeTransaction)).(*IFastBridgeBridgeTransaction) + + return out0, err + } -// NewFastBridgeMockTransactor creates a new write-only instance of FastBridgeMock, bound to a specific deployed contract. -func NewFastBridgeMockTransactor(address common.Address, transactor bind.ContractTransactor) (*FastBridgeMockTransactor, error) { - contract, err := bindFastBridgeMock(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &FastBridgeMockTransactor{contract: contract}, nil +// GetBridgeTransaction is a free data retrieval call binding the contract method 0xac11fb1a. +// +// Solidity: function getBridgeTransaction(bytes request) pure returns((uint32,uint32,address,address,address,address,uint256,uint256,uint256,bool,uint256,uint256)) +func (_FastBridgeMock *FastBridgeMockSession) GetBridgeTransaction(request []byte) (IFastBridgeBridgeTransaction, error) { + return _FastBridgeMock.Contract.GetBridgeTransaction(&_FastBridgeMock.CallOpts, request) } -// NewFastBridgeMockFilterer creates a new log filterer instance of FastBridgeMock, bound to a specific deployed contract. -func NewFastBridgeMockFilterer(address common.Address, filterer bind.ContractFilterer) (*FastBridgeMockFilterer, error) { - contract, err := bindFastBridgeMock(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &FastBridgeMockFilterer{contract: contract}, nil +// GetBridgeTransaction is a free data retrieval call binding the contract method 0xac11fb1a. +// +// Solidity: function getBridgeTransaction(bytes request) pure returns((uint32,uint32,address,address,address,address,uint256,uint256,uint256,bool,uint256,uint256)) +func (_FastBridgeMock *FastBridgeMockCallerSession) GetBridgeTransaction(request []byte) (IFastBridgeBridgeTransaction, error) { + return _FastBridgeMock.Contract.GetBridgeTransaction(&_FastBridgeMock.CallOpts, request) } -// bindFastBridgeMock binds a generic wrapper to an already deployed contract. -func bindFastBridgeMock(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := FastBridgeMockMetaData.GetAbi() +// GetEnumKeyByValue is a free data retrieval call binding the contract method 0x85ad903d. +// +// Solidity: function getEnumKeyByValue(uint8 keyValue) pure returns(string) +func (_FastBridgeMock *FastBridgeMockCaller) GetEnumKeyByValue(opts *bind.CallOpts, keyValue uint8) (string, error) { + var out []interface{} + err := _FastBridgeMock.contract.Call(opts, &out, "getEnumKeyByValue", keyValue) + if err != nil { - return nil, err + return *new(string), err } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_FastBridgeMock *FastBridgeMockRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _FastBridgeMock.Contract.FastBridgeMockCaller.contract.Call(opts, result, method, params...) -} -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_FastBridgeMock *FastBridgeMockRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _FastBridgeMock.Contract.FastBridgeMockTransactor.contract.Transfer(opts) -} + out0 := *abi.ConvertType(out[0], new(string)).(*string) -// Transact invokes the (paid) contract method with params as input values. -func (_FastBridgeMock *FastBridgeMockRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _FastBridgeMock.Contract.FastBridgeMockTransactor.contract.Transact(opts, method, params...) -} + return out0, err -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_FastBridgeMock *FastBridgeMockCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _FastBridgeMock.Contract.contract.Call(opts, result, method, params...) } -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_FastBridgeMock *FastBridgeMockTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _FastBridgeMock.Contract.contract.Transfer(opts) +// GetEnumKeyByValue is a free data retrieval call binding the contract method 0x85ad903d. +// +// Solidity: function getEnumKeyByValue(uint8 keyValue) pure returns(string) +func (_FastBridgeMock *FastBridgeMockSession) GetEnumKeyByValue(keyValue uint8) (string, error) { + return _FastBridgeMock.Contract.GetEnumKeyByValue(&_FastBridgeMock.CallOpts, keyValue) } -// Transact invokes the (paid) contract method with params as input values. -func (_FastBridgeMock *FastBridgeMockTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _FastBridgeMock.Contract.contract.Transact(opts, method, params...) +// GetEnumKeyByValue is a free data retrieval call binding the contract method 0x85ad903d. +// +// Solidity: function getEnumKeyByValue(uint8 keyValue) pure returns(string) +func (_FastBridgeMock *FastBridgeMockCallerSession) GetEnumKeyByValue(keyValue uint8) (string, error) { + return _FastBridgeMock.Contract.GetEnumKeyByValue(&_FastBridgeMock.CallOpts, keyValue) } -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. // -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_FastBridgeMock *FastBridgeMockCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_FastBridgeMock *FastBridgeMockCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { var out []interface{} - err := _FastBridgeMock.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") + err := _FastBridgeMock.contract.Call(opts, &out, "getRoleAdmin", role) if err != nil { return *new([32]byte), err @@ -8108,57 +7871,57 @@ func (_FastBridgeMock *FastBridgeMockCaller) DEFAULTADMINROLE(opts *bind.CallOpt } -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. // -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_FastBridgeMock *FastBridgeMockSession) DEFAULTADMINROLE() ([32]byte, error) { - return _FastBridgeMock.Contract.DEFAULTADMINROLE(&_FastBridgeMock.CallOpts) +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_FastBridgeMock *FastBridgeMockSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _FastBridgeMock.Contract.GetRoleAdmin(&_FastBridgeMock.CallOpts, role) } -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. // -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_FastBridgeMock *FastBridgeMockCallerSession) DEFAULTADMINROLE() ([32]byte, error) { - return _FastBridgeMock.Contract.DEFAULTADMINROLE(&_FastBridgeMock.CallOpts) +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_FastBridgeMock *FastBridgeMockCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _FastBridgeMock.Contract.GetRoleAdmin(&_FastBridgeMock.CallOpts, role) } -// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. // -// Solidity: function FEE_BPS() view returns(uint256) -func (_FastBridgeMock *FastBridgeMockCaller) FEEBPS(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_FastBridgeMock *FastBridgeMockCaller) GetRoleMember(opts *bind.CallOpts, role [32]byte, index *big.Int) (common.Address, error) { var out []interface{} - err := _FastBridgeMock.contract.Call(opts, &out, "FEE_BPS") + err := _FastBridgeMock.contract.Call(opts, &out, "getRoleMember", role, index) if err != nil { - return *new(*big.Int), err + return *new(common.Address), err } - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) return out0, err } -// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. // -// Solidity: function FEE_BPS() view returns(uint256) -func (_FastBridgeMock *FastBridgeMockSession) FEEBPS() (*big.Int, error) { - return _FastBridgeMock.Contract.FEEBPS(&_FastBridgeMock.CallOpts) +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_FastBridgeMock *FastBridgeMockSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _FastBridgeMock.Contract.GetRoleMember(&_FastBridgeMock.CallOpts, role, index) } -// FEEBPS is a free data retrieval call binding the contract method 0xbf333f2c. +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. // -// Solidity: function FEE_BPS() view returns(uint256) -func (_FastBridgeMock *FastBridgeMockCallerSession) FEEBPS() (*big.Int, error) { - return _FastBridgeMock.Contract.FEEBPS(&_FastBridgeMock.CallOpts) +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_FastBridgeMock *FastBridgeMockCallerSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _FastBridgeMock.Contract.GetRoleMember(&_FastBridgeMock.CallOpts, role, index) } -// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. // -// Solidity: function FEE_RATE_MAX() view returns(uint256) -func (_FastBridgeMock *FastBridgeMockCaller) FEERATEMAX(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_FastBridgeMock *FastBridgeMockCaller) GetRoleMemberCount(opts *bind.CallOpts, role [32]byte) (*big.Int, error) { var out []interface{} - err := _FastBridgeMock.contract.Call(opts, &out, "FEE_RATE_MAX") + err := _FastBridgeMock.contract.Call(opts, &out, "getRoleMemberCount", role) if err != nil { return *new(*big.Int), err @@ -8170,1852 +7933,493 @@ func (_FastBridgeMock *FastBridgeMockCaller) FEERATEMAX(opts *bind.CallOpts) (*b } -// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. // -// Solidity: function FEE_RATE_MAX() view returns(uint256) -func (_FastBridgeMock *FastBridgeMockSession) FEERATEMAX() (*big.Int, error) { - return _FastBridgeMock.Contract.FEERATEMAX(&_FastBridgeMock.CallOpts) +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_FastBridgeMock *FastBridgeMockSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _FastBridgeMock.Contract.GetRoleMemberCount(&_FastBridgeMock.CallOpts, role) } -// FEERATEMAX is a free data retrieval call binding the contract method 0x0f5f6ed7. +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. // -// Solidity: function FEE_RATE_MAX() view returns(uint256) -func (_FastBridgeMock *FastBridgeMockCallerSession) FEERATEMAX() (*big.Int, error) { - return _FastBridgeMock.Contract.FEERATEMAX(&_FastBridgeMock.CallOpts) +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_FastBridgeMock *FastBridgeMockCallerSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _FastBridgeMock.Contract.GetRoleMemberCount(&_FastBridgeMock.CallOpts, role) } -// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. +// HasRole is a free data retrieval call binding the contract method 0x91d14854. // -// Solidity: function GOVERNOR_ROLE() view returns(bytes32) -func (_FastBridgeMock *FastBridgeMockCaller) GOVERNORROLE(opts *bind.CallOpts) ([32]byte, error) { +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_FastBridgeMock *FastBridgeMockCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { var out []interface{} - err := _FastBridgeMock.contract.Call(opts, &out, "GOVERNOR_ROLE") + err := _FastBridgeMock.contract.Call(opts, &out, "hasRole", role, account) if err != nil { - return *new([32]byte), err + return *new(bool), err } - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) return out0, err } -// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. +// HasRole is a free data retrieval call binding the contract method 0x91d14854. // -// Solidity: function GOVERNOR_ROLE() view returns(bytes32) -func (_FastBridgeMock *FastBridgeMockSession) GOVERNORROLE() ([32]byte, error) { - return _FastBridgeMock.Contract.GOVERNORROLE(&_FastBridgeMock.CallOpts) +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_FastBridgeMock *FastBridgeMockSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _FastBridgeMock.Contract.HasRole(&_FastBridgeMock.CallOpts, role, account) } -// GOVERNORROLE is a free data retrieval call binding the contract method 0xccc57490. +// HasRole is a free data retrieval call binding the contract method 0x91d14854. // -// Solidity: function GOVERNOR_ROLE() view returns(bytes32) -func (_FastBridgeMock *FastBridgeMockCallerSession) GOVERNORROLE() ([32]byte, error) { - return _FastBridgeMock.Contract.GOVERNORROLE(&_FastBridgeMock.CallOpts) +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_FastBridgeMock *FastBridgeMockCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _FastBridgeMock.Contract.HasRole(&_FastBridgeMock.CallOpts, role, account) } -// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. +// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. // -// Solidity: function GUARD_ROLE() view returns(bytes32) -func (_FastBridgeMock *FastBridgeMockCaller) GUARDROLE(opts *bind.CallOpts) ([32]byte, error) { +// Solidity: function nonce() view returns(uint256) +func (_FastBridgeMock *FastBridgeMockCaller) Nonce(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _FastBridgeMock.contract.Call(opts, &out, "GUARD_ROLE") + err := _FastBridgeMock.contract.Call(opts, &out, "nonce") if err != nil { - return *new([32]byte), err + return *new(*big.Int), err } - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) return out0, err } -// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. +// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. // -// Solidity: function GUARD_ROLE() view returns(bytes32) -func (_FastBridgeMock *FastBridgeMockSession) GUARDROLE() ([32]byte, error) { - return _FastBridgeMock.Contract.GUARDROLE(&_FastBridgeMock.CallOpts) +// Solidity: function nonce() view returns(uint256) +func (_FastBridgeMock *FastBridgeMockSession) Nonce() (*big.Int, error) { + return _FastBridgeMock.Contract.Nonce(&_FastBridgeMock.CallOpts) } -// GUARDROLE is a free data retrieval call binding the contract method 0x03ed0ee5. +// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. // -// Solidity: function GUARD_ROLE() view returns(bytes32) -func (_FastBridgeMock *FastBridgeMockCallerSession) GUARDROLE() ([32]byte, error) { - return _FastBridgeMock.Contract.GUARDROLE(&_FastBridgeMock.CallOpts) +// Solidity: function nonce() view returns(uint256) +func (_FastBridgeMock *FastBridgeMockCallerSession) Nonce() (*big.Int, error) { + return _FastBridgeMock.Contract.Nonce(&_FastBridgeMock.CallOpts) } -// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. +// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. // -// Solidity: function RELAYER_ROLE() view returns(bytes32) -func (_FastBridgeMock *FastBridgeMockCaller) RELAYERROLE(opts *bind.CallOpts) ([32]byte, error) { +// Solidity: function protocolFeeRate() view returns(uint256) +func (_FastBridgeMock *FastBridgeMockCaller) ProtocolFeeRate(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _FastBridgeMock.contract.Call(opts, &out, "RELAYER_ROLE") + err := _FastBridgeMock.contract.Call(opts, &out, "protocolFeeRate") if err != nil { - return *new([32]byte), err + return *new(*big.Int), err } - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) return out0, err } -// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. +// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. // -// Solidity: function RELAYER_ROLE() view returns(bytes32) -func (_FastBridgeMock *FastBridgeMockSession) RELAYERROLE() ([32]byte, error) { - return _FastBridgeMock.Contract.RELAYERROLE(&_FastBridgeMock.CallOpts) +// Solidity: function protocolFeeRate() view returns(uint256) +func (_FastBridgeMock *FastBridgeMockSession) ProtocolFeeRate() (*big.Int, error) { + return _FastBridgeMock.Contract.ProtocolFeeRate(&_FastBridgeMock.CallOpts) } -// RELAYERROLE is a free data retrieval call binding the contract method 0x926d7d7f. +// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. // -// Solidity: function RELAYER_ROLE() view returns(bytes32) -func (_FastBridgeMock *FastBridgeMockCallerSession) RELAYERROLE() ([32]byte, error) { - return _FastBridgeMock.Contract.RELAYERROLE(&_FastBridgeMock.CallOpts) +// Solidity: function protocolFeeRate() view returns(uint256) +func (_FastBridgeMock *FastBridgeMockCallerSession) ProtocolFeeRate() (*big.Int, error) { + return _FastBridgeMock.Contract.ProtocolFeeRate(&_FastBridgeMock.CallOpts) } -// CanClaim is a free data retrieval call binding the contract method 0xaa9641ab. +// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. // -// Solidity: function canClaim(bytes32 transactionid, address relayer) view returns(bool) -func (_FastBridgeMock *FastBridgeMockCaller) CanClaim(opts *bind.CallOpts, transactionid [32]byte, relayer common.Address) (bool, error) { +// Solidity: function protocolFees(address ) view returns(uint256) +func (_FastBridgeMock *FastBridgeMockCaller) ProtocolFees(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { var out []interface{} - err := _FastBridgeMock.contract.Call(opts, &out, "canClaim", transactionid, relayer) + err := _FastBridgeMock.contract.Call(opts, &out, "protocolFees", arg0) if err != nil { - return *new(bool), err + return *new(*big.Int), err } - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) return out0, err } -// CanClaim is a free data retrieval call binding the contract method 0xaa9641ab. +// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. // -// Solidity: function canClaim(bytes32 transactionid, address relayer) view returns(bool) -func (_FastBridgeMock *FastBridgeMockSession) CanClaim(transactionid [32]byte, relayer common.Address) (bool, error) { - return _FastBridgeMock.Contract.CanClaim(&_FastBridgeMock.CallOpts, transactionid, relayer) +// Solidity: function protocolFees(address ) view returns(uint256) +func (_FastBridgeMock *FastBridgeMockSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { + return _FastBridgeMock.Contract.ProtocolFees(&_FastBridgeMock.CallOpts, arg0) } -// CanClaim is a free data retrieval call binding the contract method 0xaa9641ab. +// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. // -// Solidity: function canClaim(bytes32 transactionid, address relayer) view returns(bool) -func (_FastBridgeMock *FastBridgeMockCallerSession) CanClaim(transactionid [32]byte, relayer common.Address) (bool, error) { - return _FastBridgeMock.Contract.CanClaim(&_FastBridgeMock.CallOpts, transactionid, relayer) +// Solidity: function protocolFees(address ) view returns(uint256) +func (_FastBridgeMock *FastBridgeMockCallerSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { + return _FastBridgeMock.Contract.ProtocolFees(&_FastBridgeMock.CallOpts, arg0) } -// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: function chainGasAmount() view returns(uint256) -func (_FastBridgeMock *FastBridgeMockCaller) ChainGasAmount(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_FastBridgeMock *FastBridgeMockCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { var out []interface{} - err := _FastBridgeMock.contract.Call(opts, &out, "chainGasAmount") + err := _FastBridgeMock.contract.Call(opts, &out, "supportsInterface", interfaceId) if err != nil { - return *new(*big.Int), err + return *new(bool), err } - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) return out0, err } -// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: function chainGasAmount() view returns(uint256) -func (_FastBridgeMock *FastBridgeMockSession) ChainGasAmount() (*big.Int, error) { - return _FastBridgeMock.Contract.ChainGasAmount(&_FastBridgeMock.CallOpts) +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_FastBridgeMock *FastBridgeMockSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _FastBridgeMock.Contract.SupportsInterface(&_FastBridgeMock.CallOpts, interfaceId) } -// ChainGasAmount is a free data retrieval call binding the contract method 0xe00a83e0. +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. // -// Solidity: function chainGasAmount() view returns(uint256) -func (_FastBridgeMock *FastBridgeMockCallerSession) ChainGasAmount() (*big.Int, error) { - return _FastBridgeMock.Contract.ChainGasAmount(&_FastBridgeMock.CallOpts) +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_FastBridgeMock *FastBridgeMockCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _FastBridgeMock.Contract.SupportsInterface(&_FastBridgeMock.CallOpts, interfaceId) } -// DeployBlock is a free data retrieval call binding the contract method 0xa3ec191a. +// Bridge is a paid mutator transaction binding the contract method 0x45851694. // -// Solidity: function deployBlock() view returns(uint256) -func (_FastBridgeMock *FastBridgeMockCaller) DeployBlock(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _FastBridgeMock.contract.Call(opts, &out, "deployBlock") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - +// Solidity: function bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256) params) payable returns() +func (_FastBridgeMock *FastBridgeMockTransactor) Bridge(opts *bind.TransactOpts, params IFastBridgeBridgeParams) (*types.Transaction, error) { + return _FastBridgeMock.contract.Transact(opts, "bridge", params) } -// DeployBlock is a free data retrieval call binding the contract method 0xa3ec191a. +// Bridge is a paid mutator transaction binding the contract method 0x45851694. // -// Solidity: function deployBlock() view returns(uint256) -func (_FastBridgeMock *FastBridgeMockSession) DeployBlock() (*big.Int, error) { - return _FastBridgeMock.Contract.DeployBlock(&_FastBridgeMock.CallOpts) +// Solidity: function bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256) params) payable returns() +func (_FastBridgeMock *FastBridgeMockSession) Bridge(params IFastBridgeBridgeParams) (*types.Transaction, error) { + return _FastBridgeMock.Contract.Bridge(&_FastBridgeMock.TransactOpts, params) } -// DeployBlock is a free data retrieval call binding the contract method 0xa3ec191a. +// Bridge is a paid mutator transaction binding the contract method 0x45851694. // -// Solidity: function deployBlock() view returns(uint256) -func (_FastBridgeMock *FastBridgeMockCallerSession) DeployBlock() (*big.Int, error) { - return _FastBridgeMock.Contract.DeployBlock(&_FastBridgeMock.CallOpts) +// Solidity: function bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256) params) payable returns() +func (_FastBridgeMock *FastBridgeMockTransactorSession) Bridge(params IFastBridgeBridgeParams) (*types.Transaction, error) { + return _FastBridgeMock.Contract.Bridge(&_FastBridgeMock.TransactOpts, params) } -// GetBridgeTransaction is a free data retrieval call binding the contract method 0xac11fb1a. +// Claim is a paid mutator transaction binding the contract method 0x41fcb612. // -// Solidity: function getBridgeTransaction(bytes request) pure returns((uint32,uint32,address,address,address,address,uint256,uint256,uint256,bool,uint256,uint256)) -func (_FastBridgeMock *FastBridgeMockCaller) GetBridgeTransaction(opts *bind.CallOpts, request []byte) (IFastBridgeBridgeTransaction, error) { - var out []interface{} - err := _FastBridgeMock.contract.Call(opts, &out, "getBridgeTransaction", request) - - if err != nil { - return *new(IFastBridgeBridgeTransaction), err - } - - out0 := *abi.ConvertType(out[0], new(IFastBridgeBridgeTransaction)).(*IFastBridgeBridgeTransaction) - - return out0, err - +// Solidity: function claim(bytes request, address to) returns() +func (_FastBridgeMock *FastBridgeMockTransactor) Claim(opts *bind.TransactOpts, request []byte, to common.Address) (*types.Transaction, error) { + return _FastBridgeMock.contract.Transact(opts, "claim", request, to) } -// GetBridgeTransaction is a free data retrieval call binding the contract method 0xac11fb1a. +// Claim is a paid mutator transaction binding the contract method 0x41fcb612. // -// Solidity: function getBridgeTransaction(bytes request) pure returns((uint32,uint32,address,address,address,address,uint256,uint256,uint256,bool,uint256,uint256)) -func (_FastBridgeMock *FastBridgeMockSession) GetBridgeTransaction(request []byte) (IFastBridgeBridgeTransaction, error) { - return _FastBridgeMock.Contract.GetBridgeTransaction(&_FastBridgeMock.CallOpts, request) +// Solidity: function claim(bytes request, address to) returns() +func (_FastBridgeMock *FastBridgeMockSession) Claim(request []byte, to common.Address) (*types.Transaction, error) { + return _FastBridgeMock.Contract.Claim(&_FastBridgeMock.TransactOpts, request, to) } -// GetBridgeTransaction is a free data retrieval call binding the contract method 0xac11fb1a. +// Claim is a paid mutator transaction binding the contract method 0x41fcb612. // -// Solidity: function getBridgeTransaction(bytes request) pure returns((uint32,uint32,address,address,address,address,uint256,uint256,uint256,bool,uint256,uint256)) -func (_FastBridgeMock *FastBridgeMockCallerSession) GetBridgeTransaction(request []byte) (IFastBridgeBridgeTransaction, error) { - return _FastBridgeMock.Contract.GetBridgeTransaction(&_FastBridgeMock.CallOpts, request) +// Solidity: function claim(bytes request, address to) returns() +func (_FastBridgeMock *FastBridgeMockTransactorSession) Claim(request []byte, to common.Address) (*types.Transaction, error) { + return _FastBridgeMock.Contract.Claim(&_FastBridgeMock.TransactOpts, request, to) } -// GetEnumKeyByValue is a free data retrieval call binding the contract method 0x85ad903d. +// Dispute is a paid mutator transaction binding the contract method 0xadd98c70. // -// Solidity: function getEnumKeyByValue(uint8 keyValue) pure returns(string) -func (_FastBridgeMock *FastBridgeMockCaller) GetEnumKeyByValue(opts *bind.CallOpts, keyValue uint8) (string, error) { - var out []interface{} - err := _FastBridgeMock.contract.Call(opts, &out, "getEnumKeyByValue", keyValue) - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - +// Solidity: function dispute(bytes32 transactionId) returns() +func (_FastBridgeMock *FastBridgeMockTransactor) Dispute(opts *bind.TransactOpts, transactionId [32]byte) (*types.Transaction, error) { + return _FastBridgeMock.contract.Transact(opts, "dispute", transactionId) } -// GetEnumKeyByValue is a free data retrieval call binding the contract method 0x85ad903d. +// Dispute is a paid mutator transaction binding the contract method 0xadd98c70. // -// Solidity: function getEnumKeyByValue(uint8 keyValue) pure returns(string) -func (_FastBridgeMock *FastBridgeMockSession) GetEnumKeyByValue(keyValue uint8) (string, error) { - return _FastBridgeMock.Contract.GetEnumKeyByValue(&_FastBridgeMock.CallOpts, keyValue) +// Solidity: function dispute(bytes32 transactionId) returns() +func (_FastBridgeMock *FastBridgeMockSession) Dispute(transactionId [32]byte) (*types.Transaction, error) { + return _FastBridgeMock.Contract.Dispute(&_FastBridgeMock.TransactOpts, transactionId) } -// GetEnumKeyByValue is a free data retrieval call binding the contract method 0x85ad903d. +// Dispute is a paid mutator transaction binding the contract method 0xadd98c70. // -// Solidity: function getEnumKeyByValue(uint8 keyValue) pure returns(string) -func (_FastBridgeMock *FastBridgeMockCallerSession) GetEnumKeyByValue(keyValue uint8) (string, error) { - return _FastBridgeMock.Contract.GetEnumKeyByValue(&_FastBridgeMock.CallOpts, keyValue) +// Solidity: function dispute(bytes32 transactionId) returns() +func (_FastBridgeMock *FastBridgeMockTransactorSession) Dispute(transactionId [32]byte) (*types.Transaction, error) { + return _FastBridgeMock.Contract.Dispute(&_FastBridgeMock.TransactOpts, transactionId) } -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. // -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_FastBridgeMock *FastBridgeMockCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { - var out []interface{} - err := _FastBridgeMock.contract.Call(opts, &out, "getRoleAdmin", role) +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_FastBridgeMock *FastBridgeMockTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _FastBridgeMock.contract.Transact(opts, "grantRole", role, account) +} - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. // -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_FastBridgeMock *FastBridgeMockSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { - return _FastBridgeMock.Contract.GetRoleAdmin(&_FastBridgeMock.CallOpts, role) +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_FastBridgeMock *FastBridgeMockSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _FastBridgeMock.Contract.GrantRole(&_FastBridgeMock.TransactOpts, role, account) } -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. // -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_FastBridgeMock *FastBridgeMockCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { - return _FastBridgeMock.Contract.GetRoleAdmin(&_FastBridgeMock.CallOpts, role) +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_FastBridgeMock *FastBridgeMockTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _FastBridgeMock.Contract.GrantRole(&_FastBridgeMock.TransactOpts, role, account) } -// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// MockBridgeRelayer is a paid mutator transaction binding the contract method 0xc72870cc. // -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_FastBridgeMock *FastBridgeMockCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { - var out []interface{} - err := _FastBridgeMock.contract.Call(opts, &out, "hasRole", role, account) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - +// Solidity: function mockBridgeRelayer(bytes32 transactionId, address relayer, address to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) returns() +func (_FastBridgeMock *FastBridgeMockTransactor) MockBridgeRelayer(opts *bind.TransactOpts, transactionId [32]byte, relayer common.Address, to common.Address, originChainId uint32, originToken common.Address, destToken common.Address, originAmount *big.Int, destAmount *big.Int, chainGasAmount *big.Int) (*types.Transaction, error) { + return _FastBridgeMock.contract.Transact(opts, "mockBridgeRelayer", transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount) } -// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// MockBridgeRelayer is a paid mutator transaction binding the contract method 0xc72870cc. // -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_FastBridgeMock *FastBridgeMockSession) HasRole(role [32]byte, account common.Address) (bool, error) { - return _FastBridgeMock.Contract.HasRole(&_FastBridgeMock.CallOpts, role, account) +// Solidity: function mockBridgeRelayer(bytes32 transactionId, address relayer, address to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) returns() +func (_FastBridgeMock *FastBridgeMockSession) MockBridgeRelayer(transactionId [32]byte, relayer common.Address, to common.Address, originChainId uint32, originToken common.Address, destToken common.Address, originAmount *big.Int, destAmount *big.Int, chainGasAmount *big.Int) (*types.Transaction, error) { + return _FastBridgeMock.Contract.MockBridgeRelayer(&_FastBridgeMock.TransactOpts, transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount) } -// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// MockBridgeRelayer is a paid mutator transaction binding the contract method 0xc72870cc. // -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_FastBridgeMock *FastBridgeMockCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { - return _FastBridgeMock.Contract.HasRole(&_FastBridgeMock.CallOpts, role, account) +// Solidity: function mockBridgeRelayer(bytes32 transactionId, address relayer, address to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) returns() +func (_FastBridgeMock *FastBridgeMockTransactorSession) MockBridgeRelayer(transactionId [32]byte, relayer common.Address, to common.Address, originChainId uint32, originToken common.Address, destToken common.Address, originAmount *big.Int, destAmount *big.Int, chainGasAmount *big.Int) (*types.Transaction, error) { + return _FastBridgeMock.Contract.MockBridgeRelayer(&_FastBridgeMock.TransactOpts, transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount) } -// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. +// MockBridgeRequest is a paid mutator transaction binding the contract method 0xacaebbf1. // -// Solidity: function nonce() view returns(uint256) -func (_FastBridgeMock *FastBridgeMockCaller) Nonce(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _FastBridgeMock.contract.Call(opts, &out, "nonce") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - +// Solidity: function mockBridgeRequest(bytes32 transactionId, address sender, (uint32,address,address,address,address,uint256,uint256,bool,uint256) params) returns() +func (_FastBridgeMock *FastBridgeMockTransactor) MockBridgeRequest(opts *bind.TransactOpts, transactionId [32]byte, sender common.Address, params IFastBridgeBridgeParams) (*types.Transaction, error) { + return _FastBridgeMock.contract.Transact(opts, "mockBridgeRequest", transactionId, sender, params) } -// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. +// MockBridgeRequest is a paid mutator transaction binding the contract method 0xacaebbf1. // -// Solidity: function nonce() view returns(uint256) -func (_FastBridgeMock *FastBridgeMockSession) Nonce() (*big.Int, error) { - return _FastBridgeMock.Contract.Nonce(&_FastBridgeMock.CallOpts) +// Solidity: function mockBridgeRequest(bytes32 transactionId, address sender, (uint32,address,address,address,address,uint256,uint256,bool,uint256) params) returns() +func (_FastBridgeMock *FastBridgeMockSession) MockBridgeRequest(transactionId [32]byte, sender common.Address, params IFastBridgeBridgeParams) (*types.Transaction, error) { + return _FastBridgeMock.Contract.MockBridgeRequest(&_FastBridgeMock.TransactOpts, transactionId, sender, params) } -// Nonce is a free data retrieval call binding the contract method 0xaffed0e0. +// MockBridgeRequest is a paid mutator transaction binding the contract method 0xacaebbf1. // -// Solidity: function nonce() view returns(uint256) -func (_FastBridgeMock *FastBridgeMockCallerSession) Nonce() (*big.Int, error) { - return _FastBridgeMock.Contract.Nonce(&_FastBridgeMock.CallOpts) +// Solidity: function mockBridgeRequest(bytes32 transactionId, address sender, (uint32,address,address,address,address,uint256,uint256,bool,uint256) params) returns() +func (_FastBridgeMock *FastBridgeMockTransactorSession) MockBridgeRequest(transactionId [32]byte, sender common.Address, params IFastBridgeBridgeParams) (*types.Transaction, error) { + return _FastBridgeMock.Contract.MockBridgeRequest(&_FastBridgeMock.TransactOpts, transactionId, sender, params) } -// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// MockBridgeRequestRaw is a paid mutator transaction binding the contract method 0xaedf009d. // -// Solidity: function protocolFeeRate() view returns(uint256) -func (_FastBridgeMock *FastBridgeMockCaller) ProtocolFeeRate(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _FastBridgeMock.contract.Call(opts, &out, "protocolFeeRate") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - +// Solidity: function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes request) returns() +func (_FastBridgeMock *FastBridgeMockTransactor) MockBridgeRequestRaw(opts *bind.TransactOpts, transactionId [32]byte, sender common.Address, request []byte) (*types.Transaction, error) { + return _FastBridgeMock.contract.Transact(opts, "mockBridgeRequestRaw", transactionId, sender, request) } -// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// MockBridgeRequestRaw is a paid mutator transaction binding the contract method 0xaedf009d. // -// Solidity: function protocolFeeRate() view returns(uint256) -func (_FastBridgeMock *FastBridgeMockSession) ProtocolFeeRate() (*big.Int, error) { - return _FastBridgeMock.Contract.ProtocolFeeRate(&_FastBridgeMock.CallOpts) +// Solidity: function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes request) returns() +func (_FastBridgeMock *FastBridgeMockSession) MockBridgeRequestRaw(transactionId [32]byte, sender common.Address, request []byte) (*types.Transaction, error) { + return _FastBridgeMock.Contract.MockBridgeRequestRaw(&_FastBridgeMock.TransactOpts, transactionId, sender, request) } -// ProtocolFeeRate is a free data retrieval call binding the contract method 0x58f85880. +// MockBridgeRequestRaw is a paid mutator transaction binding the contract method 0xaedf009d. // -// Solidity: function protocolFeeRate() view returns(uint256) -func (_FastBridgeMock *FastBridgeMockCallerSession) ProtocolFeeRate() (*big.Int, error) { - return _FastBridgeMock.Contract.ProtocolFeeRate(&_FastBridgeMock.CallOpts) +// Solidity: function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes request) returns() +func (_FastBridgeMock *FastBridgeMockTransactorSession) MockBridgeRequestRaw(transactionId [32]byte, sender common.Address, request []byte) (*types.Transaction, error) { + return _FastBridgeMock.Contract.MockBridgeRequestRaw(&_FastBridgeMock.TransactOpts, transactionId, sender, request) } -// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. +// Prove is a paid mutator transaction binding the contract method 0x886d36ff. // -// Solidity: function protocolFees(address ) view returns(uint256) -func (_FastBridgeMock *FastBridgeMockCaller) ProtocolFees(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { - var out []interface{} - err := _FastBridgeMock.contract.Call(opts, &out, "protocolFees", arg0) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - +// Solidity: function prove(bytes request, bytes32 destTxHash) returns() +func (_FastBridgeMock *FastBridgeMockTransactor) Prove(opts *bind.TransactOpts, request []byte, destTxHash [32]byte) (*types.Transaction, error) { + return _FastBridgeMock.contract.Transact(opts, "prove", request, destTxHash) } -// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. +// Prove is a paid mutator transaction binding the contract method 0x886d36ff. // -// Solidity: function protocolFees(address ) view returns(uint256) -func (_FastBridgeMock *FastBridgeMockSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { - return _FastBridgeMock.Contract.ProtocolFees(&_FastBridgeMock.CallOpts, arg0) +// Solidity: function prove(bytes request, bytes32 destTxHash) returns() +func (_FastBridgeMock *FastBridgeMockSession) Prove(request []byte, destTxHash [32]byte) (*types.Transaction, error) { + return _FastBridgeMock.Contract.Prove(&_FastBridgeMock.TransactOpts, request, destTxHash) } -// ProtocolFees is a free data retrieval call binding the contract method 0xdcf844a7. +// Prove is a paid mutator transaction binding the contract method 0x886d36ff. // -// Solidity: function protocolFees(address ) view returns(uint256) -func (_FastBridgeMock *FastBridgeMockCallerSession) ProtocolFees(arg0 common.Address) (*big.Int, error) { - return _FastBridgeMock.Contract.ProtocolFees(&_FastBridgeMock.CallOpts, arg0) +// Solidity: function prove(bytes request, bytes32 destTxHash) returns() +func (_FastBridgeMock *FastBridgeMockTransactorSession) Prove(request []byte, destTxHash [32]byte) (*types.Transaction, error) { + return _FastBridgeMock.Contract.Prove(&_FastBridgeMock.TransactOpts, request, destTxHash) } -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// Refund is a paid mutator transaction binding the contract method 0x5eb7d946. // -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_FastBridgeMock *FastBridgeMockCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { - var out []interface{} - err := _FastBridgeMock.contract.Call(opts, &out, "supportsInterface", interfaceId) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - +// Solidity: function refund(bytes request) returns() +func (_FastBridgeMock *FastBridgeMockTransactor) Refund(opts *bind.TransactOpts, request []byte) (*types.Transaction, error) { + return _FastBridgeMock.contract.Transact(opts, "refund", request) } -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// Refund is a paid mutator transaction binding the contract method 0x5eb7d946. // -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_FastBridgeMock *FastBridgeMockSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _FastBridgeMock.Contract.SupportsInterface(&_FastBridgeMock.CallOpts, interfaceId) +// Solidity: function refund(bytes request) returns() +func (_FastBridgeMock *FastBridgeMockSession) Refund(request []byte) (*types.Transaction, error) { + return _FastBridgeMock.Contract.Refund(&_FastBridgeMock.TransactOpts, request) } -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// Refund is a paid mutator transaction binding the contract method 0x5eb7d946. // -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_FastBridgeMock *FastBridgeMockCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _FastBridgeMock.Contract.SupportsInterface(&_FastBridgeMock.CallOpts, interfaceId) +// Solidity: function refund(bytes request) returns() +func (_FastBridgeMock *FastBridgeMockTransactorSession) Refund(request []byte) (*types.Transaction, error) { + return _FastBridgeMock.Contract.Refund(&_FastBridgeMock.TransactOpts, request) } -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. +// Relay is a paid mutator transaction binding the contract method 0x8f0d6f17. // -// Solidity: function addGovernor(address _governor) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) AddGovernor(opts *bind.TransactOpts, _governor common.Address) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "addGovernor", _governor) +// Solidity: function relay(bytes request) payable returns() +func (_FastBridgeMock *FastBridgeMockTransactor) Relay(opts *bind.TransactOpts, request []byte) (*types.Transaction, error) { + return _FastBridgeMock.contract.Transact(opts, "relay", request) } -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. +// Relay is a paid mutator transaction binding the contract method 0x8f0d6f17. // -// Solidity: function addGovernor(address _governor) returns() -func (_FastBridgeMock *FastBridgeMockSession) AddGovernor(_governor common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.AddGovernor(&_FastBridgeMock.TransactOpts, _governor) +// Solidity: function relay(bytes request) payable returns() +func (_FastBridgeMock *FastBridgeMockSession) Relay(request []byte) (*types.Transaction, error) { + return _FastBridgeMock.Contract.Relay(&_FastBridgeMock.TransactOpts, request) } -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. +// Relay is a paid mutator transaction binding the contract method 0x8f0d6f17. // -// Solidity: function addGovernor(address _governor) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) AddGovernor(_governor common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.AddGovernor(&_FastBridgeMock.TransactOpts, _governor) +// Solidity: function relay(bytes request) payable returns() +func (_FastBridgeMock *FastBridgeMockTransactorSession) Relay(request []byte) (*types.Transaction, error) { + return _FastBridgeMock.Contract.Relay(&_FastBridgeMock.TransactOpts, request) } -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. // -// Solidity: function addGuard(address _guard) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) AddGuard(opts *bind.TransactOpts, _guard common.Address) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "addGuard", _guard) +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_FastBridgeMock *FastBridgeMockTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _FastBridgeMock.contract.Transact(opts, "renounceRole", role, callerConfirmation) } -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. // -// Solidity: function addGuard(address _guard) returns() -func (_FastBridgeMock *FastBridgeMockSession) AddGuard(_guard common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.AddGuard(&_FastBridgeMock.TransactOpts, _guard) +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_FastBridgeMock *FastBridgeMockSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _FastBridgeMock.Contract.RenounceRole(&_FastBridgeMock.TransactOpts, role, callerConfirmation) } -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. // -// Solidity: function addGuard(address _guard) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) AddGuard(_guard common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.AddGuard(&_FastBridgeMock.TransactOpts, _guard) +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_FastBridgeMock *FastBridgeMockTransactorSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _FastBridgeMock.Contract.RenounceRole(&_FastBridgeMock.TransactOpts, role, callerConfirmation) } -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. // -// Solidity: function addRelayer(address _relayer) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) AddRelayer(opts *bind.TransactOpts, _relayer common.Address) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "addRelayer", _relayer) +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_FastBridgeMock *FastBridgeMockTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _FastBridgeMock.contract.Transact(opts, "revokeRole", role, account) } -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. // -// Solidity: function addRelayer(address _relayer) returns() -func (_FastBridgeMock *FastBridgeMockSession) AddRelayer(_relayer common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.AddRelayer(&_FastBridgeMock.TransactOpts, _relayer) +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_FastBridgeMock *FastBridgeMockSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _FastBridgeMock.Contract.RevokeRole(&_FastBridgeMock.TransactOpts, role, account) } -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. // -// Solidity: function addRelayer(address _relayer) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) AddRelayer(_relayer common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.AddRelayer(&_FastBridgeMock.TransactOpts, _relayer) +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_FastBridgeMock *FastBridgeMockTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _FastBridgeMock.Contract.RevokeRole(&_FastBridgeMock.TransactOpts, role, account) } -// Bridge is a paid mutator transaction binding the contract method 0x45851694. +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. // -// Solidity: function bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256) params) payable returns() -func (_FastBridgeMock *FastBridgeMockTransactor) Bridge(opts *bind.TransactOpts, params IFastBridgeBridgeParams) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "bridge", params) +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_FastBridgeMock *FastBridgeMockTransactor) SetChainGasAmount(opts *bind.TransactOpts, newChainGasAmount *big.Int) (*types.Transaction, error) { + return _FastBridgeMock.contract.Transact(opts, "setChainGasAmount", newChainGasAmount) } -// Bridge is a paid mutator transaction binding the contract method 0x45851694. +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. // -// Solidity: function bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256) params) payable returns() -func (_FastBridgeMock *FastBridgeMockSession) Bridge(params IFastBridgeBridgeParams) (*types.Transaction, error) { - return _FastBridgeMock.Contract.Bridge(&_FastBridgeMock.TransactOpts, params) +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_FastBridgeMock *FastBridgeMockSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { + return _FastBridgeMock.Contract.SetChainGasAmount(&_FastBridgeMock.TransactOpts, newChainGasAmount) } -// Bridge is a paid mutator transaction binding the contract method 0x45851694. +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. // -// Solidity: function bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256) params) payable returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) Bridge(params IFastBridgeBridgeParams) (*types.Transaction, error) { - return _FastBridgeMock.Contract.Bridge(&_FastBridgeMock.TransactOpts, params) +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_FastBridgeMock *FastBridgeMockTransactorSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { + return _FastBridgeMock.Contract.SetChainGasAmount(&_FastBridgeMock.TransactOpts, newChainGasAmount) } -// Claim is a paid mutator transaction binding the contract method 0x41fcb612. -// -// Solidity: function claim(bytes request, address to) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) Claim(opts *bind.TransactOpts, request []byte, to common.Address) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "claim", request, to) -} - -// Claim is a paid mutator transaction binding the contract method 0x41fcb612. -// -// Solidity: function claim(bytes request, address to) returns() -func (_FastBridgeMock *FastBridgeMockSession) Claim(request []byte, to common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.Claim(&_FastBridgeMock.TransactOpts, request, to) -} - -// Claim is a paid mutator transaction binding the contract method 0x41fcb612. -// -// Solidity: function claim(bytes request, address to) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) Claim(request []byte, to common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.Claim(&_FastBridgeMock.TransactOpts, request, to) -} - -// Dispute is a paid mutator transaction binding the contract method 0xadd98c70. -// -// Solidity: function dispute(bytes32 transactionId) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) Dispute(opts *bind.TransactOpts, transactionId [32]byte) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "dispute", transactionId) -} - -// Dispute is a paid mutator transaction binding the contract method 0xadd98c70. -// -// Solidity: function dispute(bytes32 transactionId) returns() -func (_FastBridgeMock *FastBridgeMockSession) Dispute(transactionId [32]byte) (*types.Transaction, error) { - return _FastBridgeMock.Contract.Dispute(&_FastBridgeMock.TransactOpts, transactionId) -} - -// Dispute is a paid mutator transaction binding the contract method 0xadd98c70. -// -// Solidity: function dispute(bytes32 transactionId) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) Dispute(transactionId [32]byte) (*types.Transaction, error) { - return _FastBridgeMock.Contract.Dispute(&_FastBridgeMock.TransactOpts, transactionId) -} - -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. -// -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "grantRole", role, account) -} - -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. -// -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_FastBridgeMock *FastBridgeMockSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.GrantRole(&_FastBridgeMock.TransactOpts, role, account) -} - -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. -// -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.GrantRole(&_FastBridgeMock.TransactOpts, role, account) -} - -// MockBridgeRelayer is a paid mutator transaction binding the contract method 0xc72870cc. -// -// Solidity: function mockBridgeRelayer(bytes32 transactionId, address relayer, address to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) MockBridgeRelayer(opts *bind.TransactOpts, transactionId [32]byte, relayer common.Address, to common.Address, originChainId uint32, originToken common.Address, destToken common.Address, originAmount *big.Int, destAmount *big.Int, chainGasAmount *big.Int) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "mockBridgeRelayer", transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount) -} - -// MockBridgeRelayer is a paid mutator transaction binding the contract method 0xc72870cc. -// -// Solidity: function mockBridgeRelayer(bytes32 transactionId, address relayer, address to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) returns() -func (_FastBridgeMock *FastBridgeMockSession) MockBridgeRelayer(transactionId [32]byte, relayer common.Address, to common.Address, originChainId uint32, originToken common.Address, destToken common.Address, originAmount *big.Int, destAmount *big.Int, chainGasAmount *big.Int) (*types.Transaction, error) { - return _FastBridgeMock.Contract.MockBridgeRelayer(&_FastBridgeMock.TransactOpts, transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount) -} - -// MockBridgeRelayer is a paid mutator transaction binding the contract method 0xc72870cc. -// -// Solidity: function mockBridgeRelayer(bytes32 transactionId, address relayer, address to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) MockBridgeRelayer(transactionId [32]byte, relayer common.Address, to common.Address, originChainId uint32, originToken common.Address, destToken common.Address, originAmount *big.Int, destAmount *big.Int, chainGasAmount *big.Int) (*types.Transaction, error) { - return _FastBridgeMock.Contract.MockBridgeRelayer(&_FastBridgeMock.TransactOpts, transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount) -} - -// MockBridgeRequest is a paid mutator transaction binding the contract method 0xacaebbf1. -// -// Solidity: function mockBridgeRequest(bytes32 transactionId, address sender, (uint32,address,address,address,address,uint256,uint256,bool,uint256) params) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) MockBridgeRequest(opts *bind.TransactOpts, transactionId [32]byte, sender common.Address, params IFastBridgeBridgeParams) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "mockBridgeRequest", transactionId, sender, params) -} - -// MockBridgeRequest is a paid mutator transaction binding the contract method 0xacaebbf1. -// -// Solidity: function mockBridgeRequest(bytes32 transactionId, address sender, (uint32,address,address,address,address,uint256,uint256,bool,uint256) params) returns() -func (_FastBridgeMock *FastBridgeMockSession) MockBridgeRequest(transactionId [32]byte, sender common.Address, params IFastBridgeBridgeParams) (*types.Transaction, error) { - return _FastBridgeMock.Contract.MockBridgeRequest(&_FastBridgeMock.TransactOpts, transactionId, sender, params) -} - -// MockBridgeRequest is a paid mutator transaction binding the contract method 0xacaebbf1. -// -// Solidity: function mockBridgeRequest(bytes32 transactionId, address sender, (uint32,address,address,address,address,uint256,uint256,bool,uint256) params) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) MockBridgeRequest(transactionId [32]byte, sender common.Address, params IFastBridgeBridgeParams) (*types.Transaction, error) { - return _FastBridgeMock.Contract.MockBridgeRequest(&_FastBridgeMock.TransactOpts, transactionId, sender, params) -} - -// MockBridgeRequestRaw is a paid mutator transaction binding the contract method 0xaedf009d. -// -// Solidity: function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes request) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) MockBridgeRequestRaw(opts *bind.TransactOpts, transactionId [32]byte, sender common.Address, request []byte) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "mockBridgeRequestRaw", transactionId, sender, request) -} - -// MockBridgeRequestRaw is a paid mutator transaction binding the contract method 0xaedf009d. -// -// Solidity: function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes request) returns() -func (_FastBridgeMock *FastBridgeMockSession) MockBridgeRequestRaw(transactionId [32]byte, sender common.Address, request []byte) (*types.Transaction, error) { - return _FastBridgeMock.Contract.MockBridgeRequestRaw(&_FastBridgeMock.TransactOpts, transactionId, sender, request) -} - -// MockBridgeRequestRaw is a paid mutator transaction binding the contract method 0xaedf009d. -// -// Solidity: function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes request) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) MockBridgeRequestRaw(transactionId [32]byte, sender common.Address, request []byte) (*types.Transaction, error) { - return _FastBridgeMock.Contract.MockBridgeRequestRaw(&_FastBridgeMock.TransactOpts, transactionId, sender, request) -} - -// Prove is a paid mutator transaction binding the contract method 0x886d36ff. -// -// Solidity: function prove(bytes request, bytes32 destTxHash) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) Prove(opts *bind.TransactOpts, request []byte, destTxHash [32]byte) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "prove", request, destTxHash) -} - -// Prove is a paid mutator transaction binding the contract method 0x886d36ff. -// -// Solidity: function prove(bytes request, bytes32 destTxHash) returns() -func (_FastBridgeMock *FastBridgeMockSession) Prove(request []byte, destTxHash [32]byte) (*types.Transaction, error) { - return _FastBridgeMock.Contract.Prove(&_FastBridgeMock.TransactOpts, request, destTxHash) -} - -// Prove is a paid mutator transaction binding the contract method 0x886d36ff. -// -// Solidity: function prove(bytes request, bytes32 destTxHash) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) Prove(request []byte, destTxHash [32]byte) (*types.Transaction, error) { - return _FastBridgeMock.Contract.Prove(&_FastBridgeMock.TransactOpts, request, destTxHash) -} - -// Refund is a paid mutator transaction binding the contract method 0x5eb7d946. -// -// Solidity: function refund(bytes request) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) Refund(opts *bind.TransactOpts, request []byte) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "refund", request) -} - -// Refund is a paid mutator transaction binding the contract method 0x5eb7d946. -// -// Solidity: function refund(bytes request) returns() -func (_FastBridgeMock *FastBridgeMockSession) Refund(request []byte) (*types.Transaction, error) { - return _FastBridgeMock.Contract.Refund(&_FastBridgeMock.TransactOpts, request) -} - -// Refund is a paid mutator transaction binding the contract method 0x5eb7d946. -// -// Solidity: function refund(bytes request) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) Refund(request []byte) (*types.Transaction, error) { - return _FastBridgeMock.Contract.Refund(&_FastBridgeMock.TransactOpts, request) -} - -// Relay is a paid mutator transaction binding the contract method 0x8f0d6f17. -// -// Solidity: function relay(bytes request) payable returns() -func (_FastBridgeMock *FastBridgeMockTransactor) Relay(opts *bind.TransactOpts, request []byte) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "relay", request) -} - -// Relay is a paid mutator transaction binding the contract method 0x8f0d6f17. -// -// Solidity: function relay(bytes request) payable returns() -func (_FastBridgeMock *FastBridgeMockSession) Relay(request []byte) (*types.Transaction, error) { - return _FastBridgeMock.Contract.Relay(&_FastBridgeMock.TransactOpts, request) -} - -// Relay is a paid mutator transaction binding the contract method 0x8f0d6f17. -// -// Solidity: function relay(bytes request) payable returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) Relay(request []byte) (*types.Transaction, error) { - return _FastBridgeMock.Contract.Relay(&_FastBridgeMock.TransactOpts, request) -} - -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. -// -// Solidity: function removeGovernor(address _governor) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) RemoveGovernor(opts *bind.TransactOpts, _governor common.Address) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "removeGovernor", _governor) -} - -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. -// -// Solidity: function removeGovernor(address _governor) returns() -func (_FastBridgeMock *FastBridgeMockSession) RemoveGovernor(_governor common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.RemoveGovernor(&_FastBridgeMock.TransactOpts, _governor) -} - -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. -// -// Solidity: function removeGovernor(address _governor) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) RemoveGovernor(_governor common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.RemoveGovernor(&_FastBridgeMock.TransactOpts, _governor) -} - -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. -// -// Solidity: function removeGuard(address _guard) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) RemoveGuard(opts *bind.TransactOpts, _guard common.Address) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "removeGuard", _guard) -} - -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. -// -// Solidity: function removeGuard(address _guard) returns() -func (_FastBridgeMock *FastBridgeMockSession) RemoveGuard(_guard common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.RemoveGuard(&_FastBridgeMock.TransactOpts, _guard) -} - -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. -// -// Solidity: function removeGuard(address _guard) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) RemoveGuard(_guard common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.RemoveGuard(&_FastBridgeMock.TransactOpts, _guard) -} - -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. -// -// Solidity: function removeRelayer(address _relayer) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) RemoveRelayer(opts *bind.TransactOpts, _relayer common.Address) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "removeRelayer", _relayer) -} - -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. -// -// Solidity: function removeRelayer(address _relayer) returns() -func (_FastBridgeMock *FastBridgeMockSession) RemoveRelayer(_relayer common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.RemoveRelayer(&_FastBridgeMock.TransactOpts, _relayer) -} - -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. -// -// Solidity: function removeRelayer(address _relayer) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) RemoveRelayer(_relayer common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.RemoveRelayer(&_FastBridgeMock.TransactOpts, _relayer) -} - -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. -// -// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "renounceRole", role, callerConfirmation) -} - -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. -// -// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() -func (_FastBridgeMock *FastBridgeMockSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.RenounceRole(&_FastBridgeMock.TransactOpts, role, callerConfirmation) -} - -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. -// -// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.RenounceRole(&_FastBridgeMock.TransactOpts, role, callerConfirmation) -} - -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. -// -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "revokeRole", role, account) -} - -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. -// -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_FastBridgeMock *FastBridgeMockSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.RevokeRole(&_FastBridgeMock.TransactOpts, role, account) -} - -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. -// -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.RevokeRole(&_FastBridgeMock.TransactOpts, role, account) -} - -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. -// -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) SetChainGasAmount(opts *bind.TransactOpts, newChainGasAmount *big.Int) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "setChainGasAmount", newChainGasAmount) -} - -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. -// -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_FastBridgeMock *FastBridgeMockSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { - return _FastBridgeMock.Contract.SetChainGasAmount(&_FastBridgeMock.TransactOpts, newChainGasAmount) -} - -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. -// -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { - return _FastBridgeMock.Contract.SetChainGasAmount(&_FastBridgeMock.TransactOpts, newChainGasAmount) -} - -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. -// -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) SetProtocolFeeRate(opts *bind.TransactOpts, newFeeRate *big.Int) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "setProtocolFeeRate", newFeeRate) -} - -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. -// -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_FastBridgeMock *FastBridgeMockSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { - return _FastBridgeMock.Contract.SetProtocolFeeRate(&_FastBridgeMock.TransactOpts, newFeeRate) -} - -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. -// -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { - return _FastBridgeMock.Contract.SetProtocolFeeRate(&_FastBridgeMock.TransactOpts, newFeeRate) -} - -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. -// -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_FastBridgeMock *FastBridgeMockTransactor) SweepProtocolFees(opts *bind.TransactOpts, token common.Address, recipient common.Address) (*types.Transaction, error) { - return _FastBridgeMock.contract.Transact(opts, "sweepProtocolFees", token, recipient) -} - -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. -// -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_FastBridgeMock *FastBridgeMockSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.SweepProtocolFees(&_FastBridgeMock.TransactOpts, token, recipient) -} - -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. -// -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_FastBridgeMock *FastBridgeMockTransactorSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { - return _FastBridgeMock.Contract.SweepProtocolFees(&_FastBridgeMock.TransactOpts, token, recipient) -} - -// FastBridgeMockBridgeDepositClaimedIterator is returned from FilterBridgeDepositClaimed and is used to iterate over the raw logs and unpacked data for BridgeDepositClaimed events raised by the FastBridgeMock contract. -type FastBridgeMockBridgeDepositClaimedIterator struct { - Event *FastBridgeMockBridgeDepositClaimed // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *FastBridgeMockBridgeDepositClaimedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(FastBridgeMockBridgeDepositClaimed) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(FastBridgeMockBridgeDepositClaimed) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeMockBridgeDepositClaimedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *FastBridgeMockBridgeDepositClaimedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// FastBridgeMockBridgeDepositClaimed represents a BridgeDepositClaimed event raised by the FastBridgeMock contract. -type FastBridgeMockBridgeDepositClaimed struct { - TransactionId [32]byte - Relayer common.Address - To common.Address - Token common.Address - Amount *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterBridgeDepositClaimed is a free log retrieval operation binding the contract event 0x582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac678. -// -// Solidity: event BridgeDepositClaimed(bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount) -func (_FastBridgeMock *FastBridgeMockFilterer) FilterBridgeDepositClaimed(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address, to []common.Address) (*FastBridgeMockBridgeDepositClaimedIterator, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "BridgeDepositClaimed", transactionIdRule, relayerRule, toRule) - if err != nil { - return nil, err - } - return &FastBridgeMockBridgeDepositClaimedIterator{contract: _FastBridgeMock.contract, event: "BridgeDepositClaimed", logs: logs, sub: sub}, nil -} - -// WatchBridgeDepositClaimed is a free log subscription operation binding the contract event 0x582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac678. -// -// Solidity: event BridgeDepositClaimed(bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount) -func (_FastBridgeMock *FastBridgeMockFilterer) WatchBridgeDepositClaimed(opts *bind.WatchOpts, sink chan<- *FastBridgeMockBridgeDepositClaimed, transactionId [][32]byte, relayer []common.Address, to []common.Address) (event.Subscription, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "BridgeDepositClaimed", transactionIdRule, relayerRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(FastBridgeMockBridgeDepositClaimed) - if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeDepositClaimed", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseBridgeDepositClaimed is a log parse operation binding the contract event 0x582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac678. -// -// Solidity: event BridgeDepositClaimed(bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount) -func (_FastBridgeMock *FastBridgeMockFilterer) ParseBridgeDepositClaimed(log types.Log) (*FastBridgeMockBridgeDepositClaimed, error) { - event := new(FastBridgeMockBridgeDepositClaimed) - if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeDepositClaimed", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// FastBridgeMockBridgeDepositRefundedIterator is returned from FilterBridgeDepositRefunded and is used to iterate over the raw logs and unpacked data for BridgeDepositRefunded events raised by the FastBridgeMock contract. -type FastBridgeMockBridgeDepositRefundedIterator struct { - Event *FastBridgeMockBridgeDepositRefunded // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *FastBridgeMockBridgeDepositRefundedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(FastBridgeMockBridgeDepositRefunded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(FastBridgeMockBridgeDepositRefunded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeMockBridgeDepositRefundedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *FastBridgeMockBridgeDepositRefundedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// FastBridgeMockBridgeDepositRefunded represents a BridgeDepositRefunded event raised by the FastBridgeMock contract. -type FastBridgeMockBridgeDepositRefunded struct { - TransactionId [32]byte - To common.Address - Token common.Address - Amount *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterBridgeDepositRefunded is a free log retrieval operation binding the contract event 0xb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958. -// -// Solidity: event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount) -func (_FastBridgeMock *FastBridgeMockFilterer) FilterBridgeDepositRefunded(opts *bind.FilterOpts, transactionId [][32]byte, to []common.Address) (*FastBridgeMockBridgeDepositRefundedIterator, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "BridgeDepositRefunded", transactionIdRule, toRule) - if err != nil { - return nil, err - } - return &FastBridgeMockBridgeDepositRefundedIterator{contract: _FastBridgeMock.contract, event: "BridgeDepositRefunded", logs: logs, sub: sub}, nil -} - -// WatchBridgeDepositRefunded is a free log subscription operation binding the contract event 0xb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958. -// -// Solidity: event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount) -func (_FastBridgeMock *FastBridgeMockFilterer) WatchBridgeDepositRefunded(opts *bind.WatchOpts, sink chan<- *FastBridgeMockBridgeDepositRefunded, transactionId [][32]byte, to []common.Address) (event.Subscription, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "BridgeDepositRefunded", transactionIdRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(FastBridgeMockBridgeDepositRefunded) - if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeDepositRefunded", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseBridgeDepositRefunded is a log parse operation binding the contract event 0xb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958. -// -// Solidity: event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount) -func (_FastBridgeMock *FastBridgeMockFilterer) ParseBridgeDepositRefunded(log types.Log) (*FastBridgeMockBridgeDepositRefunded, error) { - event := new(FastBridgeMockBridgeDepositRefunded) - if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeDepositRefunded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// FastBridgeMockBridgeProofDisputedIterator is returned from FilterBridgeProofDisputed and is used to iterate over the raw logs and unpacked data for BridgeProofDisputed events raised by the FastBridgeMock contract. -type FastBridgeMockBridgeProofDisputedIterator struct { - Event *FastBridgeMockBridgeProofDisputed // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *FastBridgeMockBridgeProofDisputedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(FastBridgeMockBridgeProofDisputed) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(FastBridgeMockBridgeProofDisputed) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeMockBridgeProofDisputedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *FastBridgeMockBridgeProofDisputedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// FastBridgeMockBridgeProofDisputed represents a BridgeProofDisputed event raised by the FastBridgeMock contract. -type FastBridgeMockBridgeProofDisputed struct { - TransactionId [32]byte - Relayer common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterBridgeProofDisputed is a free log retrieval operation binding the contract event 0x0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad4. -// -// Solidity: event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer) -func (_FastBridgeMock *FastBridgeMockFilterer) FilterBridgeProofDisputed(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address) (*FastBridgeMockBridgeProofDisputedIterator, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - - logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "BridgeProofDisputed", transactionIdRule, relayerRule) - if err != nil { - return nil, err - } - return &FastBridgeMockBridgeProofDisputedIterator{contract: _FastBridgeMock.contract, event: "BridgeProofDisputed", logs: logs, sub: sub}, nil -} - -// WatchBridgeProofDisputed is a free log subscription operation binding the contract event 0x0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad4. -// -// Solidity: event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer) -func (_FastBridgeMock *FastBridgeMockFilterer) WatchBridgeProofDisputed(opts *bind.WatchOpts, sink chan<- *FastBridgeMockBridgeProofDisputed, transactionId [][32]byte, relayer []common.Address) (event.Subscription, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - - logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "BridgeProofDisputed", transactionIdRule, relayerRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(FastBridgeMockBridgeProofDisputed) - if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeProofDisputed", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseBridgeProofDisputed is a log parse operation binding the contract event 0x0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad4. -// -// Solidity: event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer) -func (_FastBridgeMock *FastBridgeMockFilterer) ParseBridgeProofDisputed(log types.Log) (*FastBridgeMockBridgeProofDisputed, error) { - event := new(FastBridgeMockBridgeProofDisputed) - if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeProofDisputed", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// FastBridgeMockBridgeProofProvidedIterator is returned from FilterBridgeProofProvided and is used to iterate over the raw logs and unpacked data for BridgeProofProvided events raised by the FastBridgeMock contract. -type FastBridgeMockBridgeProofProvidedIterator struct { - Event *FastBridgeMockBridgeProofProvided // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *FastBridgeMockBridgeProofProvidedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(FastBridgeMockBridgeProofProvided) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(FastBridgeMockBridgeProofProvided) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeMockBridgeProofProvidedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *FastBridgeMockBridgeProofProvidedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// FastBridgeMockBridgeProofProvided represents a BridgeProofProvided event raised by the FastBridgeMock contract. -type FastBridgeMockBridgeProofProvided struct { - TransactionId [32]byte - Relayer common.Address - TransactionHash [32]byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterBridgeProofProvided is a free log retrieval operation binding the contract event 0x4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4. -// -// Solidity: event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash) -func (_FastBridgeMock *FastBridgeMockFilterer) FilterBridgeProofProvided(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address) (*FastBridgeMockBridgeProofProvidedIterator, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - - logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "BridgeProofProvided", transactionIdRule, relayerRule) - if err != nil { - return nil, err - } - return &FastBridgeMockBridgeProofProvidedIterator{contract: _FastBridgeMock.contract, event: "BridgeProofProvided", logs: logs, sub: sub}, nil -} - -// WatchBridgeProofProvided is a free log subscription operation binding the contract event 0x4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4. -// -// Solidity: event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash) -func (_FastBridgeMock *FastBridgeMockFilterer) WatchBridgeProofProvided(opts *bind.WatchOpts, sink chan<- *FastBridgeMockBridgeProofProvided, transactionId [][32]byte, relayer []common.Address) (event.Subscription, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - - logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "BridgeProofProvided", transactionIdRule, relayerRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(FastBridgeMockBridgeProofProvided) - if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeProofProvided", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseBridgeProofProvided is a log parse operation binding the contract event 0x4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4. -// -// Solidity: event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash) -func (_FastBridgeMock *FastBridgeMockFilterer) ParseBridgeProofProvided(log types.Log) (*FastBridgeMockBridgeProofProvided, error) { - event := new(FastBridgeMockBridgeProofProvided) - if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeProofProvided", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// FastBridgeMockBridgeRelayedIterator is returned from FilterBridgeRelayed and is used to iterate over the raw logs and unpacked data for BridgeRelayed events raised by the FastBridgeMock contract. -type FastBridgeMockBridgeRelayedIterator struct { - Event *FastBridgeMockBridgeRelayed // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *FastBridgeMockBridgeRelayedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(FastBridgeMockBridgeRelayed) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(FastBridgeMockBridgeRelayed) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeMockBridgeRelayedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *FastBridgeMockBridgeRelayedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// FastBridgeMockBridgeRelayed represents a BridgeRelayed event raised by the FastBridgeMock contract. -type FastBridgeMockBridgeRelayed struct { - TransactionId [32]byte - Relayer common.Address - To common.Address - OriginChainId uint32 - OriginToken common.Address - DestToken common.Address - OriginAmount *big.Int - DestAmount *big.Int - ChainGasAmount *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterBridgeRelayed is a free log retrieval operation binding the contract event 0xf8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c. -// -// Solidity: event BridgeRelayed(bytes32 indexed transactionId, address indexed relayer, address indexed to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) -func (_FastBridgeMock *FastBridgeMockFilterer) FilterBridgeRelayed(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address, to []common.Address) (*FastBridgeMockBridgeRelayedIterator, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "BridgeRelayed", transactionIdRule, relayerRule, toRule) - if err != nil { - return nil, err - } - return &FastBridgeMockBridgeRelayedIterator{contract: _FastBridgeMock.contract, event: "BridgeRelayed", logs: logs, sub: sub}, nil -} - -// WatchBridgeRelayed is a free log subscription operation binding the contract event 0xf8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c. +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. // -// Solidity: event BridgeRelayed(bytes32 indexed transactionId, address indexed relayer, address indexed to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) -func (_FastBridgeMock *FastBridgeMockFilterer) WatchBridgeRelayed(opts *bind.WatchOpts, sink chan<- *FastBridgeMockBridgeRelayed, transactionId [][32]byte, relayer []common.Address, to []common.Address) (event.Subscription, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "BridgeRelayed", transactionIdRule, relayerRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(FastBridgeMockBridgeRelayed) - if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeRelayed", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_FastBridgeMock *FastBridgeMockTransactor) SetProtocolFeeRate(opts *bind.TransactOpts, newFeeRate *big.Int) (*types.Transaction, error) { + return _FastBridgeMock.contract.Transact(opts, "setProtocolFeeRate", newFeeRate) } -// ParseBridgeRelayed is a log parse operation binding the contract event 0xf8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c. +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. // -// Solidity: event BridgeRelayed(bytes32 indexed transactionId, address indexed relayer, address indexed to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) -func (_FastBridgeMock *FastBridgeMockFilterer) ParseBridgeRelayed(log types.Log) (*FastBridgeMockBridgeRelayed, error) { - event := new(FastBridgeMockBridgeRelayed) - if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeRelayed", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// FastBridgeMockBridgeRequestedIterator is returned from FilterBridgeRequested and is used to iterate over the raw logs and unpacked data for BridgeRequested events raised by the FastBridgeMock contract. -type FastBridgeMockBridgeRequestedIterator struct { - Event *FastBridgeMockBridgeRequested // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *FastBridgeMockBridgeRequestedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(FastBridgeMockBridgeRequested) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(FastBridgeMockBridgeRequested) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeMockBridgeRequestedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *FastBridgeMockBridgeRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// FastBridgeMockBridgeRequested represents a BridgeRequested event raised by the FastBridgeMock contract. -type FastBridgeMockBridgeRequested struct { - TransactionId [32]byte - Sender common.Address - Request []byte - DestChainId uint32 - OriginToken common.Address - DestToken common.Address - OriginAmount *big.Int - DestAmount *big.Int - SendChainGas bool - Raw types.Log // Blockchain specific contextual infos +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_FastBridgeMock *FastBridgeMockSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { + return _FastBridgeMock.Contract.SetProtocolFeeRate(&_FastBridgeMock.TransactOpts, newFeeRate) } -// FilterBridgeRequested is a free log retrieval operation binding the contract event 0x120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a. +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. // -// Solidity: event BridgeRequested(bytes32 indexed transactionId, address indexed sender, bytes request, uint32 destChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, bool sendChainGas) -func (_FastBridgeMock *FastBridgeMockFilterer) FilterBridgeRequested(opts *bind.FilterOpts, transactionId [][32]byte, sender []common.Address) (*FastBridgeMockBridgeRequestedIterator, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "BridgeRequested", transactionIdRule, senderRule) - if err != nil { - return nil, err - } - return &FastBridgeMockBridgeRequestedIterator{contract: _FastBridgeMock.contract, event: "BridgeRequested", logs: logs, sub: sub}, nil +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_FastBridgeMock *FastBridgeMockTransactorSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { + return _FastBridgeMock.Contract.SetProtocolFeeRate(&_FastBridgeMock.TransactOpts, newFeeRate) } -// WatchBridgeRequested is a free log subscription operation binding the contract event 0x120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a. +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. // -// Solidity: event BridgeRequested(bytes32 indexed transactionId, address indexed sender, bytes request, uint32 destChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, bool sendChainGas) -func (_FastBridgeMock *FastBridgeMockFilterer) WatchBridgeRequested(opts *bind.WatchOpts, sink chan<- *FastBridgeMockBridgeRequested, transactionId [][32]byte, sender []common.Address) (event.Subscription, error) { - - var transactionIdRule []interface{} - for _, transactionIdItem := range transactionId { - transactionIdRule = append(transactionIdRule, transactionIdItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "BridgeRequested", transactionIdRule, senderRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(FastBridgeMockBridgeRequested) - if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeRequested", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_FastBridgeMock *FastBridgeMockTransactor) SweepProtocolFees(opts *bind.TransactOpts, token common.Address, recipient common.Address) (*types.Transaction, error) { + return _FastBridgeMock.contract.Transact(opts, "sweepProtocolFees", token, recipient) } -// ParseBridgeRequested is a log parse operation binding the contract event 0x120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a. +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. // -// Solidity: event BridgeRequested(bytes32 indexed transactionId, address indexed sender, bytes request, uint32 destChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, bool sendChainGas) -func (_FastBridgeMock *FastBridgeMockFilterer) ParseBridgeRequested(log types.Log) (*FastBridgeMockBridgeRequested, error) { - event := new(FastBridgeMockBridgeRequested) - if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_FastBridgeMock *FastBridgeMockSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { + return _FastBridgeMock.Contract.SweepProtocolFees(&_FastBridgeMock.TransactOpts, token, recipient) } -// FastBridgeMockChainGasAmountUpdatedIterator is returned from FilterChainGasAmountUpdated and is used to iterate over the raw logs and unpacked data for ChainGasAmountUpdated events raised by the FastBridgeMock contract. -type FastBridgeMockChainGasAmountUpdatedIterator struct { - Event *FastBridgeMockChainGasAmountUpdated // Event containing the contract specifics and raw log +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_FastBridgeMock *FastBridgeMockTransactorSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { + return _FastBridgeMock.Contract.SweepProtocolFees(&_FastBridgeMock.TransactOpts, token, recipient) +} + +// FastBridgeMockBridgeDepositClaimedIterator is returned from FilterBridgeDepositClaimed and is used to iterate over the raw logs and unpacked data for BridgeDepositClaimed events raised by the FastBridgeMock contract. +type FastBridgeMockBridgeDepositClaimedIterator struct { + Event *FastBridgeMockBridgeDepositClaimed // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -10029,7 +8433,7 @@ type FastBridgeMockChainGasAmountUpdatedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeMockChainGasAmountUpdatedIterator) Next() bool { +func (it *FastBridgeMockBridgeDepositClaimedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -10038,7 +8442,7 @@ func (it *FastBridgeMockChainGasAmountUpdatedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeMockChainGasAmountUpdated) + it.Event = new(FastBridgeMockBridgeDepositClaimed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -10053,7 +8457,7 @@ func (it *FastBridgeMockChainGasAmountUpdatedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeMockChainGasAmountUpdated) + it.Event = new(FastBridgeMockBridgeDepositClaimed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -10069,42 +8473,71 @@ func (it *FastBridgeMockChainGasAmountUpdatedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeMockChainGasAmountUpdatedIterator) Error() error { +func (it *FastBridgeMockBridgeDepositClaimedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeMockChainGasAmountUpdatedIterator) Close() error { +func (it *FastBridgeMockBridgeDepositClaimedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeMockChainGasAmountUpdated represents a ChainGasAmountUpdated event raised by the FastBridgeMock contract. -type FastBridgeMockChainGasAmountUpdated struct { - OldChainGasAmount *big.Int - NewChainGasAmount *big.Int - Raw types.Log // Blockchain specific contextual infos +// FastBridgeMockBridgeDepositClaimed represents a BridgeDepositClaimed event raised by the FastBridgeMock contract. +type FastBridgeMockBridgeDepositClaimed struct { + TransactionId [32]byte + Relayer common.Address + To common.Address + Token common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterChainGasAmountUpdated is a free log retrieval operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. +// FilterBridgeDepositClaimed is a free log retrieval operation binding the contract event 0x582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac678. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_FastBridgeMock *FastBridgeMockFilterer) FilterChainGasAmountUpdated(opts *bind.FilterOpts) (*FastBridgeMockChainGasAmountUpdatedIterator, error) { +// Solidity: event BridgeDepositClaimed(bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount) +func (_FastBridgeMock *FastBridgeMockFilterer) FilterBridgeDepositClaimed(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address, to []common.Address) (*FastBridgeMockBridgeDepositClaimedIterator, error) { - logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "ChainGasAmountUpdated") + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "BridgeDepositClaimed", transactionIdRule, relayerRule, toRule) if err != nil { return nil, err } - return &FastBridgeMockChainGasAmountUpdatedIterator{contract: _FastBridgeMock.contract, event: "ChainGasAmountUpdated", logs: logs, sub: sub}, nil + return &FastBridgeMockBridgeDepositClaimedIterator{contract: _FastBridgeMock.contract, event: "BridgeDepositClaimed", logs: logs, sub: sub}, nil } -// WatchChainGasAmountUpdated is a free log subscription operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. +// WatchBridgeDepositClaimed is a free log subscription operation binding the contract event 0x582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac678. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_FastBridgeMock *FastBridgeMockFilterer) WatchChainGasAmountUpdated(opts *bind.WatchOpts, sink chan<- *FastBridgeMockChainGasAmountUpdated) (event.Subscription, error) { +// Solidity: event BridgeDepositClaimed(bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount) +func (_FastBridgeMock *FastBridgeMockFilterer) WatchBridgeDepositClaimed(opts *bind.WatchOpts, sink chan<- *FastBridgeMockBridgeDepositClaimed, transactionId [][32]byte, relayer []common.Address, to []common.Address) (event.Subscription, error) { - logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "ChainGasAmountUpdated") + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "BridgeDepositClaimed", transactionIdRule, relayerRule, toRule) if err != nil { return nil, err } @@ -10114,8 +8547,8 @@ func (_FastBridgeMock *FastBridgeMockFilterer) WatchChainGasAmountUpdated(opts * select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeMockChainGasAmountUpdated) - if err := _FastBridgeMock.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { + event := new(FastBridgeMockBridgeDepositClaimed) + if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeDepositClaimed", log); err != nil { return err } event.Raw = log @@ -10136,21 +8569,21 @@ func (_FastBridgeMock *FastBridgeMockFilterer) WatchChainGasAmountUpdated(opts * }), nil } -// ParseChainGasAmountUpdated is a log parse operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. +// ParseBridgeDepositClaimed is a log parse operation binding the contract event 0x582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac678. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_FastBridgeMock *FastBridgeMockFilterer) ParseChainGasAmountUpdated(log types.Log) (*FastBridgeMockChainGasAmountUpdated, error) { - event := new(FastBridgeMockChainGasAmountUpdated) - if err := _FastBridgeMock.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { +// Solidity: event BridgeDepositClaimed(bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount) +func (_FastBridgeMock *FastBridgeMockFilterer) ParseBridgeDepositClaimed(log types.Log) (*FastBridgeMockBridgeDepositClaimed, error) { + event := new(FastBridgeMockBridgeDepositClaimed) + if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeDepositClaimed", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeMockFeeRateUpdatedIterator is returned from FilterFeeRateUpdated and is used to iterate over the raw logs and unpacked data for FeeRateUpdated events raised by the FastBridgeMock contract. -type FastBridgeMockFeeRateUpdatedIterator struct { - Event *FastBridgeMockFeeRateUpdated // Event containing the contract specifics and raw log +// FastBridgeMockBridgeDepositRefundedIterator is returned from FilterBridgeDepositRefunded and is used to iterate over the raw logs and unpacked data for BridgeDepositRefunded events raised by the FastBridgeMock contract. +type FastBridgeMockBridgeDepositRefundedIterator struct { + Event *FastBridgeMockBridgeDepositRefunded // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -10164,7 +8597,7 @@ type FastBridgeMockFeeRateUpdatedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeMockFeeRateUpdatedIterator) Next() bool { +func (it *FastBridgeMockBridgeDepositRefundedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -10173,7 +8606,7 @@ func (it *FastBridgeMockFeeRateUpdatedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeMockFeeRateUpdated) + it.Event = new(FastBridgeMockBridgeDepositRefunded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -10188,7 +8621,7 @@ func (it *FastBridgeMockFeeRateUpdatedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeMockFeeRateUpdated) + it.Event = new(FastBridgeMockBridgeDepositRefunded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -10204,42 +8637,62 @@ func (it *FastBridgeMockFeeRateUpdatedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeMockFeeRateUpdatedIterator) Error() error { +func (it *FastBridgeMockBridgeDepositRefundedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeMockFeeRateUpdatedIterator) Close() error { +func (it *FastBridgeMockBridgeDepositRefundedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeMockFeeRateUpdated represents a FeeRateUpdated event raised by the FastBridgeMock contract. -type FastBridgeMockFeeRateUpdated struct { - OldFeeRate *big.Int - NewFeeRate *big.Int - Raw types.Log // Blockchain specific contextual infos +// FastBridgeMockBridgeDepositRefunded represents a BridgeDepositRefunded event raised by the FastBridgeMock contract. +type FastBridgeMockBridgeDepositRefunded struct { + TransactionId [32]byte + To common.Address + Token common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterFeeRateUpdated is a free log retrieval operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// FilterBridgeDepositRefunded is a free log retrieval operation binding the contract event 0xb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958. // -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_FastBridgeMock *FastBridgeMockFilterer) FilterFeeRateUpdated(opts *bind.FilterOpts) (*FastBridgeMockFeeRateUpdatedIterator, error) { +// Solidity: event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount) +func (_FastBridgeMock *FastBridgeMockFilterer) FilterBridgeDepositRefunded(opts *bind.FilterOpts, transactionId [][32]byte, to []common.Address) (*FastBridgeMockBridgeDepositRefundedIterator, error) { - logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "FeeRateUpdated") + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "BridgeDepositRefunded", transactionIdRule, toRule) if err != nil { return nil, err } - return &FastBridgeMockFeeRateUpdatedIterator{contract: _FastBridgeMock.contract, event: "FeeRateUpdated", logs: logs, sub: sub}, nil + return &FastBridgeMockBridgeDepositRefundedIterator{contract: _FastBridgeMock.contract, event: "BridgeDepositRefunded", logs: logs, sub: sub}, nil } -// WatchFeeRateUpdated is a free log subscription operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// WatchBridgeDepositRefunded is a free log subscription operation binding the contract event 0xb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958. // -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_FastBridgeMock *FastBridgeMockFilterer) WatchFeeRateUpdated(opts *bind.WatchOpts, sink chan<- *FastBridgeMockFeeRateUpdated) (event.Subscription, error) { +// Solidity: event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount) +func (_FastBridgeMock *FastBridgeMockFilterer) WatchBridgeDepositRefunded(opts *bind.WatchOpts, sink chan<- *FastBridgeMockBridgeDepositRefunded, transactionId [][32]byte, to []common.Address) (event.Subscription, error) { - logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "FeeRateUpdated") + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "BridgeDepositRefunded", transactionIdRule, toRule) if err != nil { return nil, err } @@ -10249,8 +8702,8 @@ func (_FastBridgeMock *FastBridgeMockFilterer) WatchFeeRateUpdated(opts *bind.Wa select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeMockFeeRateUpdated) - if err := _FastBridgeMock.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { + event := new(FastBridgeMockBridgeDepositRefunded) + if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeDepositRefunded", log); err != nil { return err } event.Raw = log @@ -10271,21 +8724,21 @@ func (_FastBridgeMock *FastBridgeMockFilterer) WatchFeeRateUpdated(opts *bind.Wa }), nil } -// ParseFeeRateUpdated is a log parse operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// ParseBridgeDepositRefunded is a log parse operation binding the contract event 0xb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958. // -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_FastBridgeMock *FastBridgeMockFilterer) ParseFeeRateUpdated(log types.Log) (*FastBridgeMockFeeRateUpdated, error) { - event := new(FastBridgeMockFeeRateUpdated) - if err := _FastBridgeMock.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { +// Solidity: event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount) +func (_FastBridgeMock *FastBridgeMockFilterer) ParseBridgeDepositRefunded(log types.Log) (*FastBridgeMockBridgeDepositRefunded, error) { + event := new(FastBridgeMockBridgeDepositRefunded) + if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeDepositRefunded", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeMockFeesSweptIterator is returned from FilterFeesSwept and is used to iterate over the raw logs and unpacked data for FeesSwept events raised by the FastBridgeMock contract. -type FastBridgeMockFeesSweptIterator struct { - Event *FastBridgeMockFeesSwept // Event containing the contract specifics and raw log +// FastBridgeMockBridgeProofDisputedIterator is returned from FilterBridgeProofDisputed and is used to iterate over the raw logs and unpacked data for BridgeProofDisputed events raised by the FastBridgeMock contract. +type FastBridgeMockBridgeProofDisputedIterator struct { + Event *FastBridgeMockBridgeProofDisputed // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -10299,7 +8752,7 @@ type FastBridgeMockFeesSweptIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeMockFeesSweptIterator) Next() bool { +func (it *FastBridgeMockBridgeProofDisputedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -10308,7 +8761,7 @@ func (it *FastBridgeMockFeesSweptIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeMockFeesSwept) + it.Event = new(FastBridgeMockBridgeProofDisputed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -10323,7 +8776,7 @@ func (it *FastBridgeMockFeesSweptIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeMockFeesSwept) + it.Event = new(FastBridgeMockBridgeProofDisputed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -10339,43 +8792,60 @@ func (it *FastBridgeMockFeesSweptIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeMockFeesSweptIterator) Error() error { +func (it *FastBridgeMockBridgeProofDisputedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeMockFeesSweptIterator) Close() error { +func (it *FastBridgeMockBridgeProofDisputedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeMockFeesSwept represents a FeesSwept event raised by the FastBridgeMock contract. -type FastBridgeMockFeesSwept struct { - Token common.Address - Recipient common.Address - Amount *big.Int - Raw types.Log // Blockchain specific contextual infos +// FastBridgeMockBridgeProofDisputed represents a BridgeProofDisputed event raised by the FastBridgeMock contract. +type FastBridgeMockBridgeProofDisputed struct { + TransactionId [32]byte + Relayer common.Address + Raw types.Log // Blockchain specific contextual infos } -// FilterFeesSwept is a free log retrieval operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// FilterBridgeProofDisputed is a free log retrieval operation binding the contract event 0x0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad4. // -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_FastBridgeMock *FastBridgeMockFilterer) FilterFeesSwept(opts *bind.FilterOpts) (*FastBridgeMockFeesSweptIterator, error) { +// Solidity: event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer) +func (_FastBridgeMock *FastBridgeMockFilterer) FilterBridgeProofDisputed(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address) (*FastBridgeMockBridgeProofDisputedIterator, error) { - logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "FeesSwept") + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + + logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "BridgeProofDisputed", transactionIdRule, relayerRule) if err != nil { return nil, err } - return &FastBridgeMockFeesSweptIterator{contract: _FastBridgeMock.contract, event: "FeesSwept", logs: logs, sub: sub}, nil + return &FastBridgeMockBridgeProofDisputedIterator{contract: _FastBridgeMock.contract, event: "BridgeProofDisputed", logs: logs, sub: sub}, nil } -// WatchFeesSwept is a free log subscription operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// WatchBridgeProofDisputed is a free log subscription operation binding the contract event 0x0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad4. // -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_FastBridgeMock *FastBridgeMockFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink chan<- *FastBridgeMockFeesSwept) (event.Subscription, error) { +// Solidity: event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer) +func (_FastBridgeMock *FastBridgeMockFilterer) WatchBridgeProofDisputed(opts *bind.WatchOpts, sink chan<- *FastBridgeMockBridgeProofDisputed, transactionId [][32]byte, relayer []common.Address) (event.Subscription, error) { - logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "FeesSwept") + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + + logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "BridgeProofDisputed", transactionIdRule, relayerRule) if err != nil { return nil, err } @@ -10385,8 +8855,8 @@ func (_FastBridgeMock *FastBridgeMockFilterer) WatchFeesSwept(opts *bind.WatchOp select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeMockFeesSwept) - if err := _FastBridgeMock.contract.UnpackLog(event, "FeesSwept", log); err != nil { + event := new(FastBridgeMockBridgeProofDisputed) + if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeProofDisputed", log); err != nil { return err } event.Raw = log @@ -10407,21 +8877,21 @@ func (_FastBridgeMock *FastBridgeMockFilterer) WatchFeesSwept(opts *bind.WatchOp }), nil } -// ParseFeesSwept is a log parse operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// ParseBridgeProofDisputed is a log parse operation binding the contract event 0x0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad4. // -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_FastBridgeMock *FastBridgeMockFilterer) ParseFeesSwept(log types.Log) (*FastBridgeMockFeesSwept, error) { - event := new(FastBridgeMockFeesSwept) - if err := _FastBridgeMock.contract.UnpackLog(event, "FeesSwept", log); err != nil { +// Solidity: event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer) +func (_FastBridgeMock *FastBridgeMockFilterer) ParseBridgeProofDisputed(log types.Log) (*FastBridgeMockBridgeProofDisputed, error) { + event := new(FastBridgeMockBridgeProofDisputed) + if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeProofDisputed", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeMockGovernorAddedIterator is returned from FilterGovernorAdded and is used to iterate over the raw logs and unpacked data for GovernorAdded events raised by the FastBridgeMock contract. -type FastBridgeMockGovernorAddedIterator struct { - Event *FastBridgeMockGovernorAdded // Event containing the contract specifics and raw log +// FastBridgeMockBridgeProofProvidedIterator is returned from FilterBridgeProofProvided and is used to iterate over the raw logs and unpacked data for BridgeProofProvided events raised by the FastBridgeMock contract. +type FastBridgeMockBridgeProofProvidedIterator struct { + Event *FastBridgeMockBridgeProofProvided // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -10435,7 +8905,7 @@ type FastBridgeMockGovernorAddedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeMockGovernorAddedIterator) Next() bool { +func (it *FastBridgeMockBridgeProofProvidedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -10444,7 +8914,7 @@ func (it *FastBridgeMockGovernorAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeMockGovernorAdded) + it.Event = new(FastBridgeMockBridgeProofProvided) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -10459,7 +8929,7 @@ func (it *FastBridgeMockGovernorAddedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeMockGovernorAdded) + it.Event = new(FastBridgeMockBridgeProofProvided) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -10475,41 +8945,61 @@ func (it *FastBridgeMockGovernorAddedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeMockGovernorAddedIterator) Error() error { +func (it *FastBridgeMockBridgeProofProvidedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeMockGovernorAddedIterator) Close() error { +func (it *FastBridgeMockBridgeProofProvidedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeMockGovernorAdded represents a GovernorAdded event raised by the FastBridgeMock contract. -type FastBridgeMockGovernorAdded struct { - Governor common.Address - Raw types.Log // Blockchain specific contextual infos +// FastBridgeMockBridgeProofProvided represents a BridgeProofProvided event raised by the FastBridgeMock contract. +type FastBridgeMockBridgeProofProvided struct { + TransactionId [32]byte + Relayer common.Address + TransactionHash [32]byte + Raw types.Log // Blockchain specific contextual infos } -// FilterGovernorAdded is a free log retrieval operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. +// FilterBridgeProofProvided is a free log retrieval operation binding the contract event 0x4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4. // -// Solidity: event GovernorAdded(address governor) -func (_FastBridgeMock *FastBridgeMockFilterer) FilterGovernorAdded(opts *bind.FilterOpts) (*FastBridgeMockGovernorAddedIterator, error) { +// Solidity: event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash) +func (_FastBridgeMock *FastBridgeMockFilterer) FilterBridgeProofProvided(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address) (*FastBridgeMockBridgeProofProvidedIterator, error) { + + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } - logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "GovernorAdded") + logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "BridgeProofProvided", transactionIdRule, relayerRule) if err != nil { return nil, err } - return &FastBridgeMockGovernorAddedIterator{contract: _FastBridgeMock.contract, event: "GovernorAdded", logs: logs, sub: sub}, nil + return &FastBridgeMockBridgeProofProvidedIterator{contract: _FastBridgeMock.contract, event: "BridgeProofProvided", logs: logs, sub: sub}, nil } -// WatchGovernorAdded is a free log subscription operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. +// WatchBridgeProofProvided is a free log subscription operation binding the contract event 0x4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4. // -// Solidity: event GovernorAdded(address governor) -func (_FastBridgeMock *FastBridgeMockFilterer) WatchGovernorAdded(opts *bind.WatchOpts, sink chan<- *FastBridgeMockGovernorAdded) (event.Subscription, error) { +// Solidity: event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash) +func (_FastBridgeMock *FastBridgeMockFilterer) WatchBridgeProofProvided(opts *bind.WatchOpts, sink chan<- *FastBridgeMockBridgeProofProvided, transactionId [][32]byte, relayer []common.Address) (event.Subscription, error) { + + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } - logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "GovernorAdded") + logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "BridgeProofProvided", transactionIdRule, relayerRule) if err != nil { return nil, err } @@ -10519,8 +9009,8 @@ func (_FastBridgeMock *FastBridgeMockFilterer) WatchGovernorAdded(opts *bind.Wat select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeMockGovernorAdded) - if err := _FastBridgeMock.contract.UnpackLog(event, "GovernorAdded", log); err != nil { + event := new(FastBridgeMockBridgeProofProvided) + if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeProofProvided", log); err != nil { return err } event.Raw = log @@ -10541,21 +9031,21 @@ func (_FastBridgeMock *FastBridgeMockFilterer) WatchGovernorAdded(opts *bind.Wat }), nil } -// ParseGovernorAdded is a log parse operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. +// ParseBridgeProofProvided is a log parse operation binding the contract event 0x4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4. // -// Solidity: event GovernorAdded(address governor) -func (_FastBridgeMock *FastBridgeMockFilterer) ParseGovernorAdded(log types.Log) (*FastBridgeMockGovernorAdded, error) { - event := new(FastBridgeMockGovernorAdded) - if err := _FastBridgeMock.contract.UnpackLog(event, "GovernorAdded", log); err != nil { +// Solidity: event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash) +func (_FastBridgeMock *FastBridgeMockFilterer) ParseBridgeProofProvided(log types.Log) (*FastBridgeMockBridgeProofProvided, error) { + event := new(FastBridgeMockBridgeProofProvided) + if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeProofProvided", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeMockGovernorRemovedIterator is returned from FilterGovernorRemoved and is used to iterate over the raw logs and unpacked data for GovernorRemoved events raised by the FastBridgeMock contract. -type FastBridgeMockGovernorRemovedIterator struct { - Event *FastBridgeMockGovernorRemoved // Event containing the contract specifics and raw log +// FastBridgeMockBridgeRelayedIterator is returned from FilterBridgeRelayed and is used to iterate over the raw logs and unpacked data for BridgeRelayed events raised by the FastBridgeMock contract. +type FastBridgeMockBridgeRelayedIterator struct { + Event *FastBridgeMockBridgeRelayed // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -10569,7 +9059,7 @@ type FastBridgeMockGovernorRemovedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeMockGovernorRemovedIterator) Next() bool { +func (it *FastBridgeMockBridgeRelayedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -10578,7 +9068,7 @@ func (it *FastBridgeMockGovernorRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeMockGovernorRemoved) + it.Event = new(FastBridgeMockBridgeRelayed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -10593,7 +9083,7 @@ func (it *FastBridgeMockGovernorRemovedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeMockGovernorRemoved) + it.Event = new(FastBridgeMockBridgeRelayed) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -10609,41 +9099,75 @@ func (it *FastBridgeMockGovernorRemovedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeMockGovernorRemovedIterator) Error() error { +func (it *FastBridgeMockBridgeRelayedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeMockGovernorRemovedIterator) Close() error { +func (it *FastBridgeMockBridgeRelayedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeMockGovernorRemoved represents a GovernorRemoved event raised by the FastBridgeMock contract. -type FastBridgeMockGovernorRemoved struct { - Governor common.Address - Raw types.Log // Blockchain specific contextual infos +// FastBridgeMockBridgeRelayed represents a BridgeRelayed event raised by the FastBridgeMock contract. +type FastBridgeMockBridgeRelayed struct { + TransactionId [32]byte + Relayer common.Address + To common.Address + OriginChainId uint32 + OriginToken common.Address + DestToken common.Address + OriginAmount *big.Int + DestAmount *big.Int + ChainGasAmount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterGovernorRemoved is a free log retrieval operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. +// FilterBridgeRelayed is a free log retrieval operation binding the contract event 0xf8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c. // -// Solidity: event GovernorRemoved(address governor) -func (_FastBridgeMock *FastBridgeMockFilterer) FilterGovernorRemoved(opts *bind.FilterOpts) (*FastBridgeMockGovernorRemovedIterator, error) { +// Solidity: event BridgeRelayed(bytes32 indexed transactionId, address indexed relayer, address indexed to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) +func (_FastBridgeMock *FastBridgeMockFilterer) FilterBridgeRelayed(opts *bind.FilterOpts, transactionId [][32]byte, relayer []common.Address, to []common.Address) (*FastBridgeMockBridgeRelayedIterator, error) { - logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "GovernorRemoved") + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "BridgeRelayed", transactionIdRule, relayerRule, toRule) if err != nil { return nil, err } - return &FastBridgeMockGovernorRemovedIterator{contract: _FastBridgeMock.contract, event: "GovernorRemoved", logs: logs, sub: sub}, nil + return &FastBridgeMockBridgeRelayedIterator{contract: _FastBridgeMock.contract, event: "BridgeRelayed", logs: logs, sub: sub}, nil } -// WatchGovernorRemoved is a free log subscription operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. +// WatchBridgeRelayed is a free log subscription operation binding the contract event 0xf8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c. // -// Solidity: event GovernorRemoved(address governor) -func (_FastBridgeMock *FastBridgeMockFilterer) WatchGovernorRemoved(opts *bind.WatchOpts, sink chan<- *FastBridgeMockGovernorRemoved) (event.Subscription, error) { +// Solidity: event BridgeRelayed(bytes32 indexed transactionId, address indexed relayer, address indexed to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) +func (_FastBridgeMock *FastBridgeMockFilterer) WatchBridgeRelayed(opts *bind.WatchOpts, sink chan<- *FastBridgeMockBridgeRelayed, transactionId [][32]byte, relayer []common.Address, to []common.Address) (event.Subscription, error) { + + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } - logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "GovernorRemoved") + logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "BridgeRelayed", transactionIdRule, relayerRule, toRule) if err != nil { return nil, err } @@ -10653,8 +9177,8 @@ func (_FastBridgeMock *FastBridgeMockFilterer) WatchGovernorRemoved(opts *bind.W select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeMockGovernorRemoved) - if err := _FastBridgeMock.contract.UnpackLog(event, "GovernorRemoved", log); err != nil { + event := new(FastBridgeMockBridgeRelayed) + if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeRelayed", log); err != nil { return err } event.Raw = log @@ -10675,21 +9199,21 @@ func (_FastBridgeMock *FastBridgeMockFilterer) WatchGovernorRemoved(opts *bind.W }), nil } -// ParseGovernorRemoved is a log parse operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. +// ParseBridgeRelayed is a log parse operation binding the contract event 0xf8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c. // -// Solidity: event GovernorRemoved(address governor) -func (_FastBridgeMock *FastBridgeMockFilterer) ParseGovernorRemoved(log types.Log) (*FastBridgeMockGovernorRemoved, error) { - event := new(FastBridgeMockGovernorRemoved) - if err := _FastBridgeMock.contract.UnpackLog(event, "GovernorRemoved", log); err != nil { +// Solidity: event BridgeRelayed(bytes32 indexed transactionId, address indexed relayer, address indexed to, uint32 originChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, uint256 chainGasAmount) +func (_FastBridgeMock *FastBridgeMockFilterer) ParseBridgeRelayed(log types.Log) (*FastBridgeMockBridgeRelayed, error) { + event := new(FastBridgeMockBridgeRelayed) + if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeRelayed", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeMockGuardAddedIterator is returned from FilterGuardAdded and is used to iterate over the raw logs and unpacked data for GuardAdded events raised by the FastBridgeMock contract. -type FastBridgeMockGuardAddedIterator struct { - Event *FastBridgeMockGuardAdded // Event containing the contract specifics and raw log +// FastBridgeMockBridgeRequestedIterator is returned from FilterBridgeRequested and is used to iterate over the raw logs and unpacked data for BridgeRequested events raised by the FastBridgeMock contract. +type FastBridgeMockBridgeRequestedIterator struct { + Event *FastBridgeMockBridgeRequested // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -10703,7 +9227,7 @@ type FastBridgeMockGuardAddedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeMockGuardAddedIterator) Next() bool { +func (it *FastBridgeMockBridgeRequestedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -10712,7 +9236,7 @@ func (it *FastBridgeMockGuardAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeMockGuardAdded) + it.Event = new(FastBridgeMockBridgeRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -10727,7 +9251,7 @@ func (it *FastBridgeMockGuardAddedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeMockGuardAdded) + it.Event = new(FastBridgeMockBridgeRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -10743,41 +9267,67 @@ func (it *FastBridgeMockGuardAddedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeMockGuardAddedIterator) Error() error { +func (it *FastBridgeMockBridgeRequestedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeMockGuardAddedIterator) Close() error { +func (it *FastBridgeMockBridgeRequestedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeMockGuardAdded represents a GuardAdded event raised by the FastBridgeMock contract. -type FastBridgeMockGuardAdded struct { - Guard common.Address - Raw types.Log // Blockchain specific contextual infos +// FastBridgeMockBridgeRequested represents a BridgeRequested event raised by the FastBridgeMock contract. +type FastBridgeMockBridgeRequested struct { + TransactionId [32]byte + Sender common.Address + Request []byte + DestChainId uint32 + OriginToken common.Address + DestToken common.Address + OriginAmount *big.Int + DestAmount *big.Int + SendChainGas bool + Raw types.Log // Blockchain specific contextual infos } -// FilterGuardAdded is a free log retrieval operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// FilterBridgeRequested is a free log retrieval operation binding the contract event 0x120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a. // -// Solidity: event GuardAdded(address guard) -func (_FastBridgeMock *FastBridgeMockFilterer) FilterGuardAdded(opts *bind.FilterOpts) (*FastBridgeMockGuardAddedIterator, error) { +// Solidity: event BridgeRequested(bytes32 indexed transactionId, address indexed sender, bytes request, uint32 destChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, bool sendChainGas) +func (_FastBridgeMock *FastBridgeMockFilterer) FilterBridgeRequested(opts *bind.FilterOpts, transactionId [][32]byte, sender []common.Address) (*FastBridgeMockBridgeRequestedIterator, error) { + + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } - logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "GuardAdded") + logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "BridgeRequested", transactionIdRule, senderRule) if err != nil { return nil, err } - return &FastBridgeMockGuardAddedIterator{contract: _FastBridgeMock.contract, event: "GuardAdded", logs: logs, sub: sub}, nil + return &FastBridgeMockBridgeRequestedIterator{contract: _FastBridgeMock.contract, event: "BridgeRequested", logs: logs, sub: sub}, nil } -// WatchGuardAdded is a free log subscription operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// WatchBridgeRequested is a free log subscription operation binding the contract event 0x120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a. // -// Solidity: event GuardAdded(address guard) -func (_FastBridgeMock *FastBridgeMockFilterer) WatchGuardAdded(opts *bind.WatchOpts, sink chan<- *FastBridgeMockGuardAdded) (event.Subscription, error) { +// Solidity: event BridgeRequested(bytes32 indexed transactionId, address indexed sender, bytes request, uint32 destChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, bool sendChainGas) +func (_FastBridgeMock *FastBridgeMockFilterer) WatchBridgeRequested(opts *bind.WatchOpts, sink chan<- *FastBridgeMockBridgeRequested, transactionId [][32]byte, sender []common.Address) (event.Subscription, error) { + + var transactionIdRule []interface{} + for _, transactionIdItem := range transactionId { + transactionIdRule = append(transactionIdRule, transactionIdItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } - logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "GuardAdded") + logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "BridgeRequested", transactionIdRule, senderRule) if err != nil { return nil, err } @@ -10787,8 +9337,8 @@ func (_FastBridgeMock *FastBridgeMockFilterer) WatchGuardAdded(opts *bind.WatchO select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeMockGuardAdded) - if err := _FastBridgeMock.contract.UnpackLog(event, "GuardAdded", log); err != nil { + event := new(FastBridgeMockBridgeRequested) + if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeRequested", log); err != nil { return err } event.Raw = log @@ -10809,21 +9359,21 @@ func (_FastBridgeMock *FastBridgeMockFilterer) WatchGuardAdded(opts *bind.WatchO }), nil } -// ParseGuardAdded is a log parse operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// ParseBridgeRequested is a log parse operation binding the contract event 0x120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a. // -// Solidity: event GuardAdded(address guard) -func (_FastBridgeMock *FastBridgeMockFilterer) ParseGuardAdded(log types.Log) (*FastBridgeMockGuardAdded, error) { - event := new(FastBridgeMockGuardAdded) - if err := _FastBridgeMock.contract.UnpackLog(event, "GuardAdded", log); err != nil { +// Solidity: event BridgeRequested(bytes32 indexed transactionId, address indexed sender, bytes request, uint32 destChainId, address originToken, address destToken, uint256 originAmount, uint256 destAmount, bool sendChainGas) +func (_FastBridgeMock *FastBridgeMockFilterer) ParseBridgeRequested(log types.Log) (*FastBridgeMockBridgeRequested, error) { + event := new(FastBridgeMockBridgeRequested) + if err := _FastBridgeMock.contract.UnpackLog(event, "BridgeRequested", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeMockGuardRemovedIterator is returned from FilterGuardRemoved and is used to iterate over the raw logs and unpacked data for GuardRemoved events raised by the FastBridgeMock contract. -type FastBridgeMockGuardRemovedIterator struct { - Event *FastBridgeMockGuardRemoved // Event containing the contract specifics and raw log +// FastBridgeMockChainGasAmountUpdatedIterator is returned from FilterChainGasAmountUpdated and is used to iterate over the raw logs and unpacked data for ChainGasAmountUpdated events raised by the FastBridgeMock contract. +type FastBridgeMockChainGasAmountUpdatedIterator struct { + Event *FastBridgeMockChainGasAmountUpdated // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -10837,7 +9387,7 @@ type FastBridgeMockGuardRemovedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeMockGuardRemovedIterator) Next() bool { +func (it *FastBridgeMockChainGasAmountUpdatedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -10846,7 +9396,7 @@ func (it *FastBridgeMockGuardRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeMockGuardRemoved) + it.Event = new(FastBridgeMockChainGasAmountUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -10861,7 +9411,7 @@ func (it *FastBridgeMockGuardRemovedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeMockGuardRemoved) + it.Event = new(FastBridgeMockChainGasAmountUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -10877,41 +9427,42 @@ func (it *FastBridgeMockGuardRemovedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeMockGuardRemovedIterator) Error() error { +func (it *FastBridgeMockChainGasAmountUpdatedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeMockGuardRemovedIterator) Close() error { +func (it *FastBridgeMockChainGasAmountUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeMockGuardRemoved represents a GuardRemoved event raised by the FastBridgeMock contract. -type FastBridgeMockGuardRemoved struct { - Guard common.Address - Raw types.Log // Blockchain specific contextual infos +// FastBridgeMockChainGasAmountUpdated represents a ChainGasAmountUpdated event raised by the FastBridgeMock contract. +type FastBridgeMockChainGasAmountUpdated struct { + OldChainGasAmount *big.Int + NewChainGasAmount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterGuardRemoved is a free log retrieval operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// FilterChainGasAmountUpdated is a free log retrieval operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event GuardRemoved(address guard) -func (_FastBridgeMock *FastBridgeMockFilterer) FilterGuardRemoved(opts *bind.FilterOpts) (*FastBridgeMockGuardRemovedIterator, error) { +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_FastBridgeMock *FastBridgeMockFilterer) FilterChainGasAmountUpdated(opts *bind.FilterOpts) (*FastBridgeMockChainGasAmountUpdatedIterator, error) { - logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "GuardRemoved") + logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "ChainGasAmountUpdated") if err != nil { return nil, err } - return &FastBridgeMockGuardRemovedIterator{contract: _FastBridgeMock.contract, event: "GuardRemoved", logs: logs, sub: sub}, nil + return &FastBridgeMockChainGasAmountUpdatedIterator{contract: _FastBridgeMock.contract, event: "ChainGasAmountUpdated", logs: logs, sub: sub}, nil } -// WatchGuardRemoved is a free log subscription operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// WatchChainGasAmountUpdated is a free log subscription operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event GuardRemoved(address guard) -func (_FastBridgeMock *FastBridgeMockFilterer) WatchGuardRemoved(opts *bind.WatchOpts, sink chan<- *FastBridgeMockGuardRemoved) (event.Subscription, error) { +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_FastBridgeMock *FastBridgeMockFilterer) WatchChainGasAmountUpdated(opts *bind.WatchOpts, sink chan<- *FastBridgeMockChainGasAmountUpdated) (event.Subscription, error) { - logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "GuardRemoved") + logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "ChainGasAmountUpdated") if err != nil { return nil, err } @@ -10921,8 +9472,8 @@ func (_FastBridgeMock *FastBridgeMockFilterer) WatchGuardRemoved(opts *bind.Watc select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeMockGuardRemoved) - if err := _FastBridgeMock.contract.UnpackLog(event, "GuardRemoved", log); err != nil { + event := new(FastBridgeMockChainGasAmountUpdated) + if err := _FastBridgeMock.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { return err } event.Raw = log @@ -10943,21 +9494,21 @@ func (_FastBridgeMock *FastBridgeMockFilterer) WatchGuardRemoved(opts *bind.Watc }), nil } -// ParseGuardRemoved is a log parse operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// ParseChainGasAmountUpdated is a log parse operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event GuardRemoved(address guard) -func (_FastBridgeMock *FastBridgeMockFilterer) ParseGuardRemoved(log types.Log) (*FastBridgeMockGuardRemoved, error) { - event := new(FastBridgeMockGuardRemoved) - if err := _FastBridgeMock.contract.UnpackLog(event, "GuardRemoved", log); err != nil { +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_FastBridgeMock *FastBridgeMockFilterer) ParseChainGasAmountUpdated(log types.Log) (*FastBridgeMockChainGasAmountUpdated, error) { + event := new(FastBridgeMockChainGasAmountUpdated) + if err := _FastBridgeMock.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeMockRelayerAddedIterator is returned from FilterRelayerAdded and is used to iterate over the raw logs and unpacked data for RelayerAdded events raised by the FastBridgeMock contract. -type FastBridgeMockRelayerAddedIterator struct { - Event *FastBridgeMockRelayerAdded // Event containing the contract specifics and raw log +// FastBridgeMockFeeRateUpdatedIterator is returned from FilterFeeRateUpdated and is used to iterate over the raw logs and unpacked data for FeeRateUpdated events raised by the FastBridgeMock contract. +type FastBridgeMockFeeRateUpdatedIterator struct { + Event *FastBridgeMockFeeRateUpdated // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -10971,7 +9522,7 @@ type FastBridgeMockRelayerAddedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeMockRelayerAddedIterator) Next() bool { +func (it *FastBridgeMockFeeRateUpdatedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -10980,7 +9531,7 @@ func (it *FastBridgeMockRelayerAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeMockRelayerAdded) + it.Event = new(FastBridgeMockFeeRateUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -10995,7 +9546,7 @@ func (it *FastBridgeMockRelayerAddedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeMockRelayerAdded) + it.Event = new(FastBridgeMockFeeRateUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -11011,41 +9562,42 @@ func (it *FastBridgeMockRelayerAddedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeMockRelayerAddedIterator) Error() error { +func (it *FastBridgeMockFeeRateUpdatedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeMockRelayerAddedIterator) Close() error { +func (it *FastBridgeMockFeeRateUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeMockRelayerAdded represents a RelayerAdded event raised by the FastBridgeMock contract. -type FastBridgeMockRelayerAdded struct { - Relayer common.Address - Raw types.Log // Blockchain specific contextual infos +// FastBridgeMockFeeRateUpdated represents a FeeRateUpdated event raised by the FastBridgeMock contract. +type FastBridgeMockFeeRateUpdated struct { + OldFeeRate *big.Int + NewFeeRate *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterRelayerAdded is a free log retrieval operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// FilterFeeRateUpdated is a free log retrieval operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. // -// Solidity: event RelayerAdded(address relayer) -func (_FastBridgeMock *FastBridgeMockFilterer) FilterRelayerAdded(opts *bind.FilterOpts) (*FastBridgeMockRelayerAddedIterator, error) { +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_FastBridgeMock *FastBridgeMockFilterer) FilterFeeRateUpdated(opts *bind.FilterOpts) (*FastBridgeMockFeeRateUpdatedIterator, error) { - logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "RelayerAdded") + logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "FeeRateUpdated") if err != nil { return nil, err } - return &FastBridgeMockRelayerAddedIterator{contract: _FastBridgeMock.contract, event: "RelayerAdded", logs: logs, sub: sub}, nil + return &FastBridgeMockFeeRateUpdatedIterator{contract: _FastBridgeMock.contract, event: "FeeRateUpdated", logs: logs, sub: sub}, nil } -// WatchRelayerAdded is a free log subscription operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// WatchFeeRateUpdated is a free log subscription operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. // -// Solidity: event RelayerAdded(address relayer) -func (_FastBridgeMock *FastBridgeMockFilterer) WatchRelayerAdded(opts *bind.WatchOpts, sink chan<- *FastBridgeMockRelayerAdded) (event.Subscription, error) { +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_FastBridgeMock *FastBridgeMockFilterer) WatchFeeRateUpdated(opts *bind.WatchOpts, sink chan<- *FastBridgeMockFeeRateUpdated) (event.Subscription, error) { - logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "RelayerAdded") + logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "FeeRateUpdated") if err != nil { return nil, err } @@ -11055,8 +9607,8 @@ func (_FastBridgeMock *FastBridgeMockFilterer) WatchRelayerAdded(opts *bind.Watc select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeMockRelayerAdded) - if err := _FastBridgeMock.contract.UnpackLog(event, "RelayerAdded", log); err != nil { + event := new(FastBridgeMockFeeRateUpdated) + if err := _FastBridgeMock.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { return err } event.Raw = log @@ -11077,21 +9629,21 @@ func (_FastBridgeMock *FastBridgeMockFilterer) WatchRelayerAdded(opts *bind.Watc }), nil } -// ParseRelayerAdded is a log parse operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// ParseFeeRateUpdated is a log parse operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. // -// Solidity: event RelayerAdded(address relayer) -func (_FastBridgeMock *FastBridgeMockFilterer) ParseRelayerAdded(log types.Log) (*FastBridgeMockRelayerAdded, error) { - event := new(FastBridgeMockRelayerAdded) - if err := _FastBridgeMock.contract.UnpackLog(event, "RelayerAdded", log); err != nil { +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_FastBridgeMock *FastBridgeMockFilterer) ParseFeeRateUpdated(log types.Log) (*FastBridgeMockFeeRateUpdated, error) { + event := new(FastBridgeMockFeeRateUpdated) + if err := _FastBridgeMock.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -// FastBridgeMockRelayerRemovedIterator is returned from FilterRelayerRemoved and is used to iterate over the raw logs and unpacked data for RelayerRemoved events raised by the FastBridgeMock contract. -type FastBridgeMockRelayerRemovedIterator struct { - Event *FastBridgeMockRelayerRemoved // Event containing the contract specifics and raw log +// FastBridgeMockFeesSweptIterator is returned from FilterFeesSwept and is used to iterate over the raw logs and unpacked data for FeesSwept events raised by the FastBridgeMock contract. +type FastBridgeMockFeesSweptIterator struct { + Event *FastBridgeMockFeesSwept // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -11105,7 +9657,7 @@ type FastBridgeMockRelayerRemovedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *FastBridgeMockRelayerRemovedIterator) Next() bool { +func (it *FastBridgeMockFeesSweptIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -11114,7 +9666,7 @@ func (it *FastBridgeMockRelayerRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(FastBridgeMockRelayerRemoved) + it.Event = new(FastBridgeMockFeesSwept) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -11129,7 +9681,7 @@ func (it *FastBridgeMockRelayerRemovedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(FastBridgeMockRelayerRemoved) + it.Event = new(FastBridgeMockFeesSwept) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -11145,41 +9697,43 @@ func (it *FastBridgeMockRelayerRemovedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *FastBridgeMockRelayerRemovedIterator) Error() error { +func (it *FastBridgeMockFeesSweptIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *FastBridgeMockRelayerRemovedIterator) Close() error { +func (it *FastBridgeMockFeesSweptIterator) Close() error { it.sub.Unsubscribe() return nil } -// FastBridgeMockRelayerRemoved represents a RelayerRemoved event raised by the FastBridgeMock contract. -type FastBridgeMockRelayerRemoved struct { - Relayer common.Address - Raw types.Log // Blockchain specific contextual infos +// FastBridgeMockFeesSwept represents a FeesSwept event raised by the FastBridgeMock contract. +type FastBridgeMockFeesSwept struct { + Token common.Address + Recipient common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterRelayerRemoved is a free log retrieval operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// FilterFeesSwept is a free log retrieval operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. // -// Solidity: event RelayerRemoved(address relayer) -func (_FastBridgeMock *FastBridgeMockFilterer) FilterRelayerRemoved(opts *bind.FilterOpts) (*FastBridgeMockRelayerRemovedIterator, error) { +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_FastBridgeMock *FastBridgeMockFilterer) FilterFeesSwept(opts *bind.FilterOpts) (*FastBridgeMockFeesSweptIterator, error) { - logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "RelayerRemoved") + logs, sub, err := _FastBridgeMock.contract.FilterLogs(opts, "FeesSwept") if err != nil { return nil, err } - return &FastBridgeMockRelayerRemovedIterator{contract: _FastBridgeMock.contract, event: "RelayerRemoved", logs: logs, sub: sub}, nil + return &FastBridgeMockFeesSweptIterator{contract: _FastBridgeMock.contract, event: "FeesSwept", logs: logs, sub: sub}, nil } -// WatchRelayerRemoved is a free log subscription operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// WatchFeesSwept is a free log subscription operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. // -// Solidity: event RelayerRemoved(address relayer) -func (_FastBridgeMock *FastBridgeMockFilterer) WatchRelayerRemoved(opts *bind.WatchOpts, sink chan<- *FastBridgeMockRelayerRemoved) (event.Subscription, error) { +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_FastBridgeMock *FastBridgeMockFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink chan<- *FastBridgeMockFeesSwept) (event.Subscription, error) { - logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "RelayerRemoved") + logs, sub, err := _FastBridgeMock.contract.WatchLogs(opts, "FeesSwept") if err != nil { return nil, err } @@ -11189,8 +9743,8 @@ func (_FastBridgeMock *FastBridgeMockFilterer) WatchRelayerRemoved(opts *bind.Wa select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(FastBridgeMockRelayerRemoved) - if err := _FastBridgeMock.contract.UnpackLog(event, "RelayerRemoved", log); err != nil { + event := new(FastBridgeMockFeesSwept) + if err := _FastBridgeMock.contract.UnpackLog(event, "FeesSwept", log); err != nil { return err } event.Raw = log @@ -11211,12 +9765,12 @@ func (_FastBridgeMock *FastBridgeMockFilterer) WatchRelayerRemoved(opts *bind.Wa }), nil } -// ParseRelayerRemoved is a log parse operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// ParseFeesSwept is a log parse operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. // -// Solidity: event RelayerRemoved(address relayer) -func (_FastBridgeMock *FastBridgeMockFilterer) ParseRelayerRemoved(log types.Log) (*FastBridgeMockRelayerRemoved, error) { - event := new(FastBridgeMockRelayerRemoved) - if err := _FastBridgeMock.contract.UnpackLog(event, "RelayerRemoved", log); err != nil { +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_FastBridgeMock *FastBridgeMockFilterer) ParseFeesSwept(log types.Log) (*FastBridgeMockFeesSwept, error) { + event := new(FastBridgeMockFeesSwept) + if err := _FastBridgeMock.contract.UnpackLog(event, "FeesSwept", log); err != nil { return nil, err } event.Raw = log @@ -12482,128 +11036,126 @@ func (_IAccessControl *IAccessControlFilterer) ParseRoleRevoked(log types.Log) ( return event, nil } -// IAdminMetaData contains all meta data concerning the IAdmin contract. -var IAdminMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerRemoved\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"addGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"addGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"addRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"removeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"removeGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"removeRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +// IAccessControlEnumerableMetaData contains all meta data concerning the IAccessControlEnumerable contract. +var IAccessControlEnumerableMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", Sigs: map[string]string{ - "3c4a25d0": "addGovernor(address)", - "6913a63c": "addGuard(address)", - "dd39f00d": "addRelayer(address)", - "eecdac88": "removeGovernor(address)", - "b6235016": "removeGuard(address)", - "60f0a5ac": "removeRelayer(address)", - "b250fe6b": "setChainGasAmount(uint256)", - "b13aa2d6": "setProtocolFeeRate(uint256)", - "06f333f2": "sweepProtocolFees(address,address)", + "248a9ca3": "getRoleAdmin(bytes32)", + "9010d07c": "getRoleMember(bytes32,uint256)", + "ca15c873": "getRoleMemberCount(bytes32)", + "2f2ff15d": "grantRole(bytes32,address)", + "91d14854": "hasRole(bytes32,address)", + "36568abe": "renounceRole(bytes32,address)", + "d547741f": "revokeRole(bytes32,address)", }, } -// IAdminABI is the input ABI used to generate the binding from. -// Deprecated: Use IAdminMetaData.ABI instead. -var IAdminABI = IAdminMetaData.ABI +// IAccessControlEnumerableABI is the input ABI used to generate the binding from. +// Deprecated: Use IAccessControlEnumerableMetaData.ABI instead. +var IAccessControlEnumerableABI = IAccessControlEnumerableMetaData.ABI -// Deprecated: Use IAdminMetaData.Sigs instead. -// IAdminFuncSigs maps the 4-byte function signature to its string representation. -var IAdminFuncSigs = IAdminMetaData.Sigs +// Deprecated: Use IAccessControlEnumerableMetaData.Sigs instead. +// IAccessControlEnumerableFuncSigs maps the 4-byte function signature to its string representation. +var IAccessControlEnumerableFuncSigs = IAccessControlEnumerableMetaData.Sigs -// IAdmin is an auto generated Go binding around an Ethereum contract. -type IAdmin struct { - IAdminCaller // Read-only binding to the contract - IAdminTransactor // Write-only binding to the contract - IAdminFilterer // Log filterer for contract events +// IAccessControlEnumerable is an auto generated Go binding around an Ethereum contract. +type IAccessControlEnumerable struct { + IAccessControlEnumerableCaller // Read-only binding to the contract + IAccessControlEnumerableTransactor // Write-only binding to the contract + IAccessControlEnumerableFilterer // Log filterer for contract events } -// IAdminCaller is an auto generated read-only Go binding around an Ethereum contract. -type IAdminCaller struct { +// IAccessControlEnumerableCaller is an auto generated read-only Go binding around an Ethereum contract. +type IAccessControlEnumerableCaller struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// IAdminTransactor is an auto generated write-only Go binding around an Ethereum contract. -type IAdminTransactor struct { +// IAccessControlEnumerableTransactor is an auto generated write-only Go binding around an Ethereum contract. +type IAccessControlEnumerableTransactor struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// IAdminFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type IAdminFilterer struct { +// IAccessControlEnumerableFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IAccessControlEnumerableFilterer struct { contract *bind.BoundContract // Generic contract wrapper for the low level calls } -// IAdminSession is an auto generated Go binding around an Ethereum contract, +// IAccessControlEnumerableSession is an auto generated Go binding around an Ethereum contract, // with pre-set call and transact options. -type IAdminSession struct { - Contract *IAdmin // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +type IAccessControlEnumerableSession struct { + Contract *IAccessControlEnumerable // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// IAdminCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// IAccessControlEnumerableCallerSession is an auto generated read-only Go binding around an Ethereum contract, // with pre-set call options. -type IAdminCallerSession struct { - Contract *IAdminCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session +type IAccessControlEnumerableCallerSession struct { + Contract *IAccessControlEnumerableCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session } -// IAdminTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// IAccessControlEnumerableTransactorSession is an auto generated write-only Go binding around an Ethereum contract, // with pre-set transact options. -type IAdminTransactorSession struct { - Contract *IAdminTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +type IAccessControlEnumerableTransactorSession struct { + Contract *IAccessControlEnumerableTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session } -// IAdminRaw is an auto generated low-level Go binding around an Ethereum contract. -type IAdminRaw struct { - Contract *IAdmin // Generic contract binding to access the raw methods on +// IAccessControlEnumerableRaw is an auto generated low-level Go binding around an Ethereum contract. +type IAccessControlEnumerableRaw struct { + Contract *IAccessControlEnumerable // Generic contract binding to access the raw methods on } -// IAdminCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type IAdminCallerRaw struct { - Contract *IAdminCaller // Generic read-only contract binding to access the raw methods on +// IAccessControlEnumerableCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IAccessControlEnumerableCallerRaw struct { + Contract *IAccessControlEnumerableCaller // Generic read-only contract binding to access the raw methods on } -// IAdminTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type IAdminTransactorRaw struct { - Contract *IAdminTransactor // Generic write-only contract binding to access the raw methods on +// IAccessControlEnumerableTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IAccessControlEnumerableTransactorRaw struct { + Contract *IAccessControlEnumerableTransactor // Generic write-only contract binding to access the raw methods on } -// NewIAdmin creates a new instance of IAdmin, bound to a specific deployed contract. -func NewIAdmin(address common.Address, backend bind.ContractBackend) (*IAdmin, error) { - contract, err := bindIAdmin(address, backend, backend, backend) +// NewIAccessControlEnumerable creates a new instance of IAccessControlEnumerable, bound to a specific deployed contract. +func NewIAccessControlEnumerable(address common.Address, backend bind.ContractBackend) (*IAccessControlEnumerable, error) { + contract, err := bindIAccessControlEnumerable(address, backend, backend, backend) if err != nil { return nil, err } - return &IAdmin{IAdminCaller: IAdminCaller{contract: contract}, IAdminTransactor: IAdminTransactor{contract: contract}, IAdminFilterer: IAdminFilterer{contract: contract}}, nil + return &IAccessControlEnumerable{IAccessControlEnumerableCaller: IAccessControlEnumerableCaller{contract: contract}, IAccessControlEnumerableTransactor: IAccessControlEnumerableTransactor{contract: contract}, IAccessControlEnumerableFilterer: IAccessControlEnumerableFilterer{contract: contract}}, nil } -// NewIAdminCaller creates a new read-only instance of IAdmin, bound to a specific deployed contract. -func NewIAdminCaller(address common.Address, caller bind.ContractCaller) (*IAdminCaller, error) { - contract, err := bindIAdmin(address, caller, nil, nil) +// NewIAccessControlEnumerableCaller creates a new read-only instance of IAccessControlEnumerable, bound to a specific deployed contract. +func NewIAccessControlEnumerableCaller(address common.Address, caller bind.ContractCaller) (*IAccessControlEnumerableCaller, error) { + contract, err := bindIAccessControlEnumerable(address, caller, nil, nil) if err != nil { return nil, err } - return &IAdminCaller{contract: contract}, nil + return &IAccessControlEnumerableCaller{contract: contract}, nil } -// NewIAdminTransactor creates a new write-only instance of IAdmin, bound to a specific deployed contract. -func NewIAdminTransactor(address common.Address, transactor bind.ContractTransactor) (*IAdminTransactor, error) { - contract, err := bindIAdmin(address, nil, transactor, nil) +// NewIAccessControlEnumerableTransactor creates a new write-only instance of IAccessControlEnumerable, bound to a specific deployed contract. +func NewIAccessControlEnumerableTransactor(address common.Address, transactor bind.ContractTransactor) (*IAccessControlEnumerableTransactor, error) { + contract, err := bindIAccessControlEnumerable(address, nil, transactor, nil) if err != nil { return nil, err } - return &IAdminTransactor{contract: contract}, nil + return &IAccessControlEnumerableTransactor{contract: contract}, nil } -// NewIAdminFilterer creates a new log filterer instance of IAdmin, bound to a specific deployed contract. -func NewIAdminFilterer(address common.Address, filterer bind.ContractFilterer) (*IAdminFilterer, error) { - contract, err := bindIAdmin(address, nil, nil, filterer) +// NewIAccessControlEnumerableFilterer creates a new log filterer instance of IAccessControlEnumerable, bound to a specific deployed contract. +func NewIAccessControlEnumerableFilterer(address common.Address, filterer bind.ContractFilterer) (*IAccessControlEnumerableFilterer, error) { + contract, err := bindIAccessControlEnumerable(address, nil, nil, filterer) if err != nil { return nil, err } - return &IAdminFilterer{contract: contract}, nil + return &IAccessControlEnumerableFilterer{contract: contract}, nil } -// bindIAdmin binds a generic wrapper to an already deployed contract. -func bindIAdmin(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := IAdminMetaData.GetAbi() +// bindIAccessControlEnumerable binds a generic wrapper to an already deployed contract. +func bindIAccessControlEnumerable(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := IAccessControlEnumerableMetaData.GetAbi() if err != nil { return nil, err } @@ -12614,502 +11166,230 @@ func bindIAdmin(address common.Address, caller bind.ContractCaller, transactor b // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. -func (_IAdmin *IAdminRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _IAdmin.Contract.IAdminCaller.contract.Call(opts, result, method, params...) +func (_IAccessControlEnumerable *IAccessControlEnumerableRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IAccessControlEnumerable.Contract.IAccessControlEnumerableCaller.contract.Call(opts, result, method, params...) } // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. -func (_IAdmin *IAdminRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _IAdmin.Contract.IAdminTransactor.contract.Transfer(opts) +func (_IAccessControlEnumerable *IAccessControlEnumerableRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.IAccessControlEnumerableTransactor.contract.Transfer(opts) } // Transact invokes the (paid) contract method with params as input values. -func (_IAdmin *IAdminRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _IAdmin.Contract.IAdminTransactor.contract.Transact(opts, method, params...) +func (_IAccessControlEnumerable *IAccessControlEnumerableRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.IAccessControlEnumerableTransactor.contract.Transact(opts, method, params...) } // Call invokes the (constant) contract method with params as input values and // sets the output to result. The result type might be a single field for simple // returns, a slice of interfaces for anonymous returns and a struct for named // returns. -func (_IAdmin *IAdminCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _IAdmin.Contract.contract.Call(opts, result, method, params...) +func (_IAccessControlEnumerable *IAccessControlEnumerableCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IAccessControlEnumerable.Contract.contract.Call(opts, result, method, params...) } // Transfer initiates a plain transaction to move funds to the contract, calling // its default method if one is available. -func (_IAdmin *IAdminTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _IAdmin.Contract.contract.Transfer(opts) +func (_IAccessControlEnumerable *IAccessControlEnumerableTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.contract.Transfer(opts) } // Transact invokes the (paid) contract method with params as input values. -func (_IAdmin *IAdminTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _IAdmin.Contract.contract.Transact(opts, method, params...) -} - -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. -// -// Solidity: function addGovernor(address _governor) returns() -func (_IAdmin *IAdminTransactor) AddGovernor(opts *bind.TransactOpts, _governor common.Address) (*types.Transaction, error) { - return _IAdmin.contract.Transact(opts, "addGovernor", _governor) -} - -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. -// -// Solidity: function addGovernor(address _governor) returns() -func (_IAdmin *IAdminSession) AddGovernor(_governor common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.AddGovernor(&_IAdmin.TransactOpts, _governor) -} - -// AddGovernor is a paid mutator transaction binding the contract method 0x3c4a25d0. -// -// Solidity: function addGovernor(address _governor) returns() -func (_IAdmin *IAdminTransactorSession) AddGovernor(_governor common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.AddGovernor(&_IAdmin.TransactOpts, _governor) -} - -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. -// -// Solidity: function addGuard(address _guard) returns() -func (_IAdmin *IAdminTransactor) AddGuard(opts *bind.TransactOpts, _guard common.Address) (*types.Transaction, error) { - return _IAdmin.contract.Transact(opts, "addGuard", _guard) -} - -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. -// -// Solidity: function addGuard(address _guard) returns() -func (_IAdmin *IAdminSession) AddGuard(_guard common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.AddGuard(&_IAdmin.TransactOpts, _guard) -} - -// AddGuard is a paid mutator transaction binding the contract method 0x6913a63c. -// -// Solidity: function addGuard(address _guard) returns() -func (_IAdmin *IAdminTransactorSession) AddGuard(_guard common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.AddGuard(&_IAdmin.TransactOpts, _guard) -} - -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. -// -// Solidity: function addRelayer(address _relayer) returns() -func (_IAdmin *IAdminTransactor) AddRelayer(opts *bind.TransactOpts, _relayer common.Address) (*types.Transaction, error) { - return _IAdmin.contract.Transact(opts, "addRelayer", _relayer) -} - -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. -// -// Solidity: function addRelayer(address _relayer) returns() -func (_IAdmin *IAdminSession) AddRelayer(_relayer common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.AddRelayer(&_IAdmin.TransactOpts, _relayer) -} - -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. -// -// Solidity: function addRelayer(address _relayer) returns() -func (_IAdmin *IAdminTransactorSession) AddRelayer(_relayer common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.AddRelayer(&_IAdmin.TransactOpts, _relayer) -} - -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. -// -// Solidity: function removeGovernor(address _governor) returns() -func (_IAdmin *IAdminTransactor) RemoveGovernor(opts *bind.TransactOpts, _governor common.Address) (*types.Transaction, error) { - return _IAdmin.contract.Transact(opts, "removeGovernor", _governor) -} - -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. -// -// Solidity: function removeGovernor(address _governor) returns() -func (_IAdmin *IAdminSession) RemoveGovernor(_governor common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.RemoveGovernor(&_IAdmin.TransactOpts, _governor) -} - -// RemoveGovernor is a paid mutator transaction binding the contract method 0xeecdac88. -// -// Solidity: function removeGovernor(address _governor) returns() -func (_IAdmin *IAdminTransactorSession) RemoveGovernor(_governor common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.RemoveGovernor(&_IAdmin.TransactOpts, _governor) -} - -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. -// -// Solidity: function removeGuard(address _guard) returns() -func (_IAdmin *IAdminTransactor) RemoveGuard(opts *bind.TransactOpts, _guard common.Address) (*types.Transaction, error) { - return _IAdmin.contract.Transact(opts, "removeGuard", _guard) -} - -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. -// -// Solidity: function removeGuard(address _guard) returns() -func (_IAdmin *IAdminSession) RemoveGuard(_guard common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.RemoveGuard(&_IAdmin.TransactOpts, _guard) -} - -// RemoveGuard is a paid mutator transaction binding the contract method 0xb6235016. -// -// Solidity: function removeGuard(address _guard) returns() -func (_IAdmin *IAdminTransactorSession) RemoveGuard(_guard common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.RemoveGuard(&_IAdmin.TransactOpts, _guard) -} - -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. -// -// Solidity: function removeRelayer(address _relayer) returns() -func (_IAdmin *IAdminTransactor) RemoveRelayer(opts *bind.TransactOpts, _relayer common.Address) (*types.Transaction, error) { - return _IAdmin.contract.Transact(opts, "removeRelayer", _relayer) -} - -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. -// -// Solidity: function removeRelayer(address _relayer) returns() -func (_IAdmin *IAdminSession) RemoveRelayer(_relayer common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.RemoveRelayer(&_IAdmin.TransactOpts, _relayer) -} - -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. -// -// Solidity: function removeRelayer(address _relayer) returns() -func (_IAdmin *IAdminTransactorSession) RemoveRelayer(_relayer common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.RemoveRelayer(&_IAdmin.TransactOpts, _relayer) -} - -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. -// -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_IAdmin *IAdminTransactor) SetChainGasAmount(opts *bind.TransactOpts, newChainGasAmount *big.Int) (*types.Transaction, error) { - return _IAdmin.contract.Transact(opts, "setChainGasAmount", newChainGasAmount) -} - -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. -// -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_IAdmin *IAdminSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { - return _IAdmin.Contract.SetChainGasAmount(&_IAdmin.TransactOpts, newChainGasAmount) -} - -// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. -// -// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() -func (_IAdmin *IAdminTransactorSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { - return _IAdmin.Contract.SetChainGasAmount(&_IAdmin.TransactOpts, newChainGasAmount) -} - -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. -// -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_IAdmin *IAdminTransactor) SetProtocolFeeRate(opts *bind.TransactOpts, newFeeRate *big.Int) (*types.Transaction, error) { - return _IAdmin.contract.Transact(opts, "setProtocolFeeRate", newFeeRate) -} - -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. -// -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_IAdmin *IAdminSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { - return _IAdmin.Contract.SetProtocolFeeRate(&_IAdmin.TransactOpts, newFeeRate) -} - -// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. -// -// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() -func (_IAdmin *IAdminTransactorSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { - return _IAdmin.Contract.SetProtocolFeeRate(&_IAdmin.TransactOpts, newFeeRate) -} - -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. -// -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_IAdmin *IAdminTransactor) SweepProtocolFees(opts *bind.TransactOpts, token common.Address, recipient common.Address) (*types.Transaction, error) { - return _IAdmin.contract.Transact(opts, "sweepProtocolFees", token, recipient) -} - -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. -// -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_IAdmin *IAdminSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.SweepProtocolFees(&_IAdmin.TransactOpts, token, recipient) -} - -// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. -// -// Solidity: function sweepProtocolFees(address token, address recipient) returns() -func (_IAdmin *IAdminTransactorSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { - return _IAdmin.Contract.SweepProtocolFees(&_IAdmin.TransactOpts, token, recipient) -} - -// IAdminChainGasAmountUpdatedIterator is returned from FilterChainGasAmountUpdated and is used to iterate over the raw logs and unpacked data for ChainGasAmountUpdated events raised by the IAdmin contract. -type IAdminChainGasAmountUpdatedIterator struct { - Event *IAdminChainGasAmountUpdated // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *IAdminChainGasAmountUpdatedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(IAdminChainGasAmountUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(IAdminChainGasAmountUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +func (_IAccessControlEnumerable *IAccessControlEnumerableTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.contract.Transact(opts, method, params...) +} - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_IAccessControlEnumerable *IAccessControlEnumerableCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { + var out []interface{} + err := _IAccessControlEnumerable.contract.Call(opts, &out, "getRoleAdmin", role) + + if err != nil { + return *new([32]byte), err } -} -// Error returns any retrieval or parsing error occurred during filtering. -func (it *IAdminChainGasAmountUpdatedIterator) Error() error { - return it.fail + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *IAdminChainGasAmountUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_IAccessControlEnumerable *IAccessControlEnumerableSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _IAccessControlEnumerable.Contract.GetRoleAdmin(&_IAccessControlEnumerable.CallOpts, role) } -// IAdminChainGasAmountUpdated represents a ChainGasAmountUpdated event raised by the IAdmin contract. -type IAdminChainGasAmountUpdated struct { - OldChainGasAmount *big.Int - NewChainGasAmount *big.Int - Raw types.Log // Blockchain specific contextual infos +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_IAccessControlEnumerable *IAccessControlEnumerableCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _IAccessControlEnumerable.Contract.GetRoleAdmin(&_IAccessControlEnumerable.CallOpts, role) } -// FilterChainGasAmountUpdated is a free log retrieval operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_IAdmin *IAdminFilterer) FilterChainGasAmountUpdated(opts *bind.FilterOpts) (*IAdminChainGasAmountUpdatedIterator, error) { +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_IAccessControlEnumerable *IAccessControlEnumerableCaller) GetRoleMember(opts *bind.CallOpts, role [32]byte, index *big.Int) (common.Address, error) { + var out []interface{} + err := _IAccessControlEnumerable.contract.Call(opts, &out, "getRoleMember", role, index) - logs, sub, err := _IAdmin.contract.FilterLogs(opts, "ChainGasAmountUpdated") if err != nil { - return nil, err + return *new(common.Address), err } - return &IAdminChainGasAmountUpdatedIterator{contract: _IAdmin.contract, event: "ChainGasAmountUpdated", logs: logs, sub: sub}, nil + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + } -// WatchChainGasAmountUpdated is a free log subscription operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_IAdmin *IAdminFilterer) WatchChainGasAmountUpdated(opts *bind.WatchOpts, sink chan<- *IAdminChainGasAmountUpdated) (event.Subscription, error) { +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_IAccessControlEnumerable *IAccessControlEnumerableSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _IAccessControlEnumerable.Contract.GetRoleMember(&_IAccessControlEnumerable.CallOpts, role, index) +} + +// GetRoleMember is a free data retrieval call binding the contract method 0x9010d07c. +// +// Solidity: function getRoleMember(bytes32 role, uint256 index) view returns(address) +func (_IAccessControlEnumerable *IAccessControlEnumerableCallerSession) GetRoleMember(role [32]byte, index *big.Int) (common.Address, error) { + return _IAccessControlEnumerable.Contract.GetRoleMember(&_IAccessControlEnumerable.CallOpts, role, index) +} + +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. +// +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_IAccessControlEnumerable *IAccessControlEnumerableCaller) GetRoleMemberCount(opts *bind.CallOpts, role [32]byte) (*big.Int, error) { + var out []interface{} + err := _IAccessControlEnumerable.contract.Call(opts, &out, "getRoleMemberCount", role) - logs, sub, err := _IAdmin.contract.WatchLogs(opts, "ChainGasAmountUpdated") if err != nil { - return nil, err + return *new(*big.Int), err } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(IAdminChainGasAmountUpdated) - if err := _IAdmin.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { - return err - } - event.Raw = log - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + } -// ParseChainGasAmountUpdated is a log parse operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. // -// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) -func (_IAdmin *IAdminFilterer) ParseChainGasAmountUpdated(log types.Log) (*IAdminChainGasAmountUpdated, error) { - event := new(IAdminChainGasAmountUpdated) - if err := _IAdmin.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_IAccessControlEnumerable *IAccessControlEnumerableSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _IAccessControlEnumerable.Contract.GetRoleMemberCount(&_IAccessControlEnumerable.CallOpts, role) } -// IAdminFeeRateUpdatedIterator is returned from FilterFeeRateUpdated and is used to iterate over the raw logs and unpacked data for FeeRateUpdated events raised by the IAdmin contract. -type IAdminFeeRateUpdatedIterator struct { - Event *IAdminFeeRateUpdated // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// GetRoleMemberCount is a free data retrieval call binding the contract method 0xca15c873. +// +// Solidity: function getRoleMemberCount(bytes32 role) view returns(uint256) +func (_IAccessControlEnumerable *IAccessControlEnumerableCallerSession) GetRoleMemberCount(role [32]byte) (*big.Int, error) { + return _IAccessControlEnumerable.Contract.GetRoleMemberCount(&_IAccessControlEnumerable.CallOpts, role) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *IAdminFeeRateUpdatedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(IAdminFeeRateUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_IAccessControlEnumerable *IAccessControlEnumerableCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { + var out []interface{} + err := _IAccessControlEnumerable.contract.Call(opts, &out, "hasRole", role, account) - default: - return false - } + if err != nil { + return *new(bool), err } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(IAdminFeeRateUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + } -// Error returns any retrieval or parsing error occurred during filtering. -func (it *IAdminFeeRateUpdatedIterator) Error() error { - return it.fail +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_IAccessControlEnumerable *IAccessControlEnumerableSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _IAccessControlEnumerable.Contract.HasRole(&_IAccessControlEnumerable.CallOpts, role, account) } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *IAdminFeeRateUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_IAccessControlEnumerable *IAccessControlEnumerableCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _IAccessControlEnumerable.Contract.HasRole(&_IAccessControlEnumerable.CallOpts, role, account) } -// IAdminFeeRateUpdated represents a FeeRateUpdated event raised by the IAdmin contract. -type IAdminFeeRateUpdated struct { - OldFeeRate *big.Int - NewFeeRate *big.Int - Raw types.Log // Blockchain specific contextual infos +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_IAccessControlEnumerable *IAccessControlEnumerableTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _IAccessControlEnumerable.contract.Transact(opts, "grantRole", role, account) } -// FilterFeeRateUpdated is a free log retrieval operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. // -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_IAdmin *IAdminFilterer) FilterFeeRateUpdated(opts *bind.FilterOpts) (*IAdminFeeRateUpdatedIterator, error) { +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_IAccessControlEnumerable *IAccessControlEnumerableSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.GrantRole(&_IAccessControlEnumerable.TransactOpts, role, account) +} - logs, sub, err := _IAdmin.contract.FilterLogs(opts, "FeeRateUpdated") - if err != nil { - return nil, err - } - return &IAdminFeeRateUpdatedIterator{contract: _IAdmin.contract, event: "FeeRateUpdated", logs: logs, sub: sub}, nil +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_IAccessControlEnumerable *IAccessControlEnumerableTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.GrantRole(&_IAccessControlEnumerable.TransactOpts, role, account) } -// WatchFeeRateUpdated is a free log subscription operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. // -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_IAdmin *IAdminFilterer) WatchFeeRateUpdated(opts *bind.WatchOpts, sink chan<- *IAdminFeeRateUpdated) (event.Subscription, error) { +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_IAccessControlEnumerable *IAccessControlEnumerableTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _IAccessControlEnumerable.contract.Transact(opts, "renounceRole", role, callerConfirmation) +} - logs, sub, err := _IAdmin.contract.WatchLogs(opts, "FeeRateUpdated") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(IAdminFeeRateUpdated) - if err := _IAdmin.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { - return err - } - event.Raw = log +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_IAccessControlEnumerable *IAccessControlEnumerableSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.RenounceRole(&_IAccessControlEnumerable.TransactOpts, role, callerConfirmation) +} - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_IAccessControlEnumerable *IAccessControlEnumerableTransactorSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.RenounceRole(&_IAccessControlEnumerable.TransactOpts, role, callerConfirmation) } -// ParseFeeRateUpdated is a log parse operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. // -// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) -func (_IAdmin *IAdminFilterer) ParseFeeRateUpdated(log types.Log) (*IAdminFeeRateUpdated, error) { - event := new(IAdminFeeRateUpdated) - if err := _IAdmin.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_IAccessControlEnumerable *IAccessControlEnumerableTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _IAccessControlEnumerable.contract.Transact(opts, "revokeRole", role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_IAccessControlEnumerable *IAccessControlEnumerableSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.RevokeRole(&_IAccessControlEnumerable.TransactOpts, role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_IAccessControlEnumerable *IAccessControlEnumerableTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _IAccessControlEnumerable.Contract.RevokeRole(&_IAccessControlEnumerable.TransactOpts, role, account) } -// IAdminFeesSweptIterator is returned from FilterFeesSwept and is used to iterate over the raw logs and unpacked data for FeesSwept events raised by the IAdmin contract. -type IAdminFeesSweptIterator struct { - Event *IAdminFeesSwept // Event containing the contract specifics and raw log +// IAccessControlEnumerableRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the IAccessControlEnumerable contract. +type IAccessControlEnumerableRoleAdminChangedIterator struct { + Event *IAccessControlEnumerableRoleAdminChanged // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -13123,7 +11403,7 @@ type IAdminFeesSweptIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *IAdminFeesSweptIterator) Next() bool { +func (it *IAccessControlEnumerableRoleAdminChangedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -13132,7 +11412,7 @@ func (it *IAdminFeesSweptIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(IAdminFeesSwept) + it.Event = new(IAccessControlEnumerableRoleAdminChanged) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -13147,7 +11427,7 @@ func (it *IAdminFeesSweptIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(IAdminFeesSwept) + it.Event = new(IAccessControlEnumerableRoleAdminChanged) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -13163,43 +11443,69 @@ func (it *IAdminFeesSweptIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *IAdminFeesSweptIterator) Error() error { +func (it *IAccessControlEnumerableRoleAdminChangedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *IAdminFeesSweptIterator) Close() error { +func (it *IAccessControlEnumerableRoleAdminChangedIterator) Close() error { it.sub.Unsubscribe() return nil } -// IAdminFeesSwept represents a FeesSwept event raised by the IAdmin contract. -type IAdminFeesSwept struct { - Token common.Address - Recipient common.Address - Amount *big.Int - Raw types.Log // Blockchain specific contextual infos +// IAccessControlEnumerableRoleAdminChanged represents a RoleAdminChanged event raised by the IAccessControlEnumerable contract. +type IAccessControlEnumerableRoleAdminChanged struct { + Role [32]byte + PreviousAdminRole [32]byte + NewAdminRole [32]byte + Raw types.Log // Blockchain specific contextual infos } -// FilterFeesSwept is a free log retrieval operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. // -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_IAdmin *IAdminFilterer) FilterFeesSwept(opts *bind.FilterOpts) (*IAdminFeesSweptIterator, error) { +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_IAccessControlEnumerable *IAccessControlEnumerableFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*IAccessControlEnumerableRoleAdminChangedIterator, error) { - logs, sub, err := _IAdmin.contract.FilterLogs(opts, "FeesSwept") + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + } + + logs, sub, err := _IAccessControlEnumerable.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { return nil, err } - return &IAdminFeesSweptIterator{contract: _IAdmin.contract, event: "FeesSwept", logs: logs, sub: sub}, nil + return &IAccessControlEnumerableRoleAdminChangedIterator{contract: _IAccessControlEnumerable.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil } -// WatchFeesSwept is a free log subscription operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. // -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_IAdmin *IAdminFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink chan<- *IAdminFeesSwept) (event.Subscription, error) { +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_IAccessControlEnumerable *IAccessControlEnumerableFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *IAccessControlEnumerableRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { - logs, sub, err := _IAdmin.contract.WatchLogs(opts, "FeesSwept") + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + } + + logs, sub, err := _IAccessControlEnumerable.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) if err != nil { return nil, err } @@ -13209,8 +11515,8 @@ func (_IAdmin *IAdminFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink chan<- select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(IAdminFeesSwept) - if err := _IAdmin.contract.UnpackLog(event, "FeesSwept", log); err != nil { + event := new(IAccessControlEnumerableRoleAdminChanged) + if err := _IAccessControlEnumerable.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { return err } event.Raw = log @@ -13231,21 +11537,21 @@ func (_IAdmin *IAdminFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink chan<- }), nil } -// ParseFeesSwept is a log parse operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. +// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. // -// Solidity: event FeesSwept(address token, address recipient, uint256 amount) -func (_IAdmin *IAdminFilterer) ParseFeesSwept(log types.Log) (*IAdminFeesSwept, error) { - event := new(IAdminFeesSwept) - if err := _IAdmin.contract.UnpackLog(event, "FeesSwept", log); err != nil { +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_IAccessControlEnumerable *IAccessControlEnumerableFilterer) ParseRoleAdminChanged(log types.Log) (*IAccessControlEnumerableRoleAdminChanged, error) { + event := new(IAccessControlEnumerableRoleAdminChanged) + if err := _IAccessControlEnumerable.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { return nil, err } event.Raw = log return event, nil } -// IAdminGovernorAddedIterator is returned from FilterGovernorAdded and is used to iterate over the raw logs and unpacked data for GovernorAdded events raised by the IAdmin contract. -type IAdminGovernorAddedIterator struct { - Event *IAdminGovernorAdded // Event containing the contract specifics and raw log +// IAccessControlEnumerableRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the IAccessControlEnumerable contract. +type IAccessControlEnumerableRoleGrantedIterator struct { + Event *IAccessControlEnumerableRoleGranted // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -13259,7 +11565,7 @@ type IAdminGovernorAddedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *IAdminGovernorAddedIterator) Next() bool { +func (it *IAccessControlEnumerableRoleGrantedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -13268,7 +11574,7 @@ func (it *IAdminGovernorAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(IAdminGovernorAdded) + it.Event = new(IAccessControlEnumerableRoleGranted) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -13283,7 +11589,7 @@ func (it *IAdminGovernorAddedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(IAdminGovernorAdded) + it.Event = new(IAccessControlEnumerableRoleGranted) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -13299,41 +11605,69 @@ func (it *IAdminGovernorAddedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *IAdminGovernorAddedIterator) Error() error { +func (it *IAccessControlEnumerableRoleGrantedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *IAdminGovernorAddedIterator) Close() error { +func (it *IAccessControlEnumerableRoleGrantedIterator) Close() error { it.sub.Unsubscribe() return nil } -// IAdminGovernorAdded represents a GovernorAdded event raised by the IAdmin contract. -type IAdminGovernorAdded struct { - Governor common.Address - Raw types.Log // Blockchain specific contextual infos +// IAccessControlEnumerableRoleGranted represents a RoleGranted event raised by the IAccessControlEnumerable contract. +type IAccessControlEnumerableRoleGranted struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos } -// FilterGovernorAdded is a free log retrieval operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. +// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. // -// Solidity: event GovernorAdded(address governor) -func (_IAdmin *IAdminFilterer) FilterGovernorAdded(opts *bind.FilterOpts) (*IAdminGovernorAddedIterator, error) { +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_IAccessControlEnumerable *IAccessControlEnumerableFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*IAccessControlEnumerableRoleGrantedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } - logs, sub, err := _IAdmin.contract.FilterLogs(opts, "GovernorAdded") + logs, sub, err := _IAccessControlEnumerable.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) if err != nil { return nil, err } - return &IAdminGovernorAddedIterator{contract: _IAdmin.contract, event: "GovernorAdded", logs: logs, sub: sub}, nil + return &IAccessControlEnumerableRoleGrantedIterator{contract: _IAccessControlEnumerable.contract, event: "RoleGranted", logs: logs, sub: sub}, nil } -// WatchGovernorAdded is a free log subscription operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. +// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. // -// Solidity: event GovernorAdded(address governor) -func (_IAdmin *IAdminFilterer) WatchGovernorAdded(opts *bind.WatchOpts, sink chan<- *IAdminGovernorAdded) (event.Subscription, error) { +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_IAccessControlEnumerable *IAccessControlEnumerableFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *IAccessControlEnumerableRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } - logs, sub, err := _IAdmin.contract.WatchLogs(opts, "GovernorAdded") + logs, sub, err := _IAccessControlEnumerable.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) if err != nil { return nil, err } @@ -13343,8 +11677,8 @@ func (_IAdmin *IAdminFilterer) WatchGovernorAdded(opts *bind.WatchOpts, sink cha select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(IAdminGovernorAdded) - if err := _IAdmin.contract.UnpackLog(event, "GovernorAdded", log); err != nil { + event := new(IAccessControlEnumerableRoleGranted) + if err := _IAccessControlEnumerable.contract.UnpackLog(event, "RoleGranted", log); err != nil { return err } event.Raw = log @@ -13365,21 +11699,21 @@ func (_IAdmin *IAdminFilterer) WatchGovernorAdded(opts *bind.WatchOpts, sink cha }), nil } -// ParseGovernorAdded is a log parse operation binding the contract event 0xdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5. +// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. // -// Solidity: event GovernorAdded(address governor) -func (_IAdmin *IAdminFilterer) ParseGovernorAdded(log types.Log) (*IAdminGovernorAdded, error) { - event := new(IAdminGovernorAdded) - if err := _IAdmin.contract.UnpackLog(event, "GovernorAdded", log); err != nil { +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_IAccessControlEnumerable *IAccessControlEnumerableFilterer) ParseRoleGranted(log types.Log) (*IAccessControlEnumerableRoleGranted, error) { + event := new(IAccessControlEnumerableRoleGranted) + if err := _IAccessControlEnumerable.contract.UnpackLog(event, "RoleGranted", log); err != nil { return nil, err } event.Raw = log return event, nil } -// IAdminGovernorRemovedIterator is returned from FilterGovernorRemoved and is used to iterate over the raw logs and unpacked data for GovernorRemoved events raised by the IAdmin contract. -type IAdminGovernorRemovedIterator struct { - Event *IAdminGovernorRemoved // Event containing the contract specifics and raw log +// IAccessControlEnumerableRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the IAccessControlEnumerable contract. +type IAccessControlEnumerableRoleRevokedIterator struct { + Event *IAccessControlEnumerableRoleRevoked // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -13393,7 +11727,7 @@ type IAdminGovernorRemovedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *IAdminGovernorRemovedIterator) Next() bool { +func (it *IAccessControlEnumerableRoleRevokedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -13402,7 +11736,7 @@ func (it *IAdminGovernorRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(IAdminGovernorRemoved) + it.Event = new(IAccessControlEnumerableRoleRevoked) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -13417,7 +11751,7 @@ func (it *IAdminGovernorRemovedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(IAdminGovernorRemoved) + it.Event = new(IAccessControlEnumerableRoleRevoked) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -13433,41 +11767,69 @@ func (it *IAdminGovernorRemovedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *IAdminGovernorRemovedIterator) Error() error { +func (it *IAccessControlEnumerableRoleRevokedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *IAdminGovernorRemovedIterator) Close() error { +func (it *IAccessControlEnumerableRoleRevokedIterator) Close() error { it.sub.Unsubscribe() return nil } -// IAdminGovernorRemoved represents a GovernorRemoved event raised by the IAdmin contract. -type IAdminGovernorRemoved struct { - Governor common.Address - Raw types.Log // Blockchain specific contextual infos +// IAccessControlEnumerableRoleRevoked represents a RoleRevoked event raised by the IAccessControlEnumerable contract. +type IAccessControlEnumerableRoleRevoked struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos } -// FilterGovernorRemoved is a free log retrieval operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. +// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. // -// Solidity: event GovernorRemoved(address governor) -func (_IAdmin *IAdminFilterer) FilterGovernorRemoved(opts *bind.FilterOpts) (*IAdminGovernorRemovedIterator, error) { +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_IAccessControlEnumerable *IAccessControlEnumerableFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*IAccessControlEnumerableRoleRevokedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } - logs, sub, err := _IAdmin.contract.FilterLogs(opts, "GovernorRemoved") + logs, sub, err := _IAccessControlEnumerable.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) if err != nil { return nil, err } - return &IAdminGovernorRemovedIterator{contract: _IAdmin.contract, event: "GovernorRemoved", logs: logs, sub: sub}, nil + return &IAccessControlEnumerableRoleRevokedIterator{contract: _IAccessControlEnumerable.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil } -// WatchGovernorRemoved is a free log subscription operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. +// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. // -// Solidity: event GovernorRemoved(address governor) -func (_IAdmin *IAdminFilterer) WatchGovernorRemoved(opts *bind.WatchOpts, sink chan<- *IAdminGovernorRemoved) (event.Subscription, error) { +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_IAccessControlEnumerable *IAccessControlEnumerableFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *IAccessControlEnumerableRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } - logs, sub, err := _IAdmin.contract.WatchLogs(opts, "GovernorRemoved") + logs, sub, err := _IAccessControlEnumerable.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) if err != nil { return nil, err } @@ -13477,8 +11839,8 @@ func (_IAdmin *IAdminFilterer) WatchGovernorRemoved(opts *bind.WatchOpts, sink c select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(IAdminGovernorRemoved) - if err := _IAdmin.contract.UnpackLog(event, "GovernorRemoved", log); err != nil { + event := new(IAccessControlEnumerableRoleRevoked) + if err := _IAccessControlEnumerable.contract.UnpackLog(event, "RoleRevoked", log); err != nil { return err } event.Raw = log @@ -13499,155 +11861,244 @@ func (_IAdmin *IAdminFilterer) WatchGovernorRemoved(opts *bind.WatchOpts, sink c }), nil } -// ParseGovernorRemoved is a log parse operation binding the contract event 0x1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b. -// -// Solidity: event GovernorRemoved(address governor) -func (_IAdmin *IAdminFilterer) ParseGovernorRemoved(log types.Log) (*IAdminGovernorRemoved, error) { - event := new(IAdminGovernorRemoved) - if err := _IAdmin.contract.UnpackLog(event, "GovernorRemoved", log); err != nil { +// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_IAccessControlEnumerable *IAccessControlEnumerableFilterer) ParseRoleRevoked(log types.Log) (*IAccessControlEnumerableRoleRevoked, error) { + event := new(IAccessControlEnumerableRoleRevoked) + if err := _IAccessControlEnumerable.contract.UnpackLog(event, "RoleRevoked", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IAdminMetaData contains all meta data concerning the IAdmin contract. +var IAdminMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Sigs: map[string]string{ + "b250fe6b": "setChainGasAmount(uint256)", + "b13aa2d6": "setProtocolFeeRate(uint256)", + "06f333f2": "sweepProtocolFees(address,address)", + }, +} + +// IAdminABI is the input ABI used to generate the binding from. +// Deprecated: Use IAdminMetaData.ABI instead. +var IAdminABI = IAdminMetaData.ABI + +// Deprecated: Use IAdminMetaData.Sigs instead. +// IAdminFuncSigs maps the 4-byte function signature to its string representation. +var IAdminFuncSigs = IAdminMetaData.Sigs + +// IAdmin is an auto generated Go binding around an Ethereum contract. +type IAdmin struct { + IAdminCaller // Read-only binding to the contract + IAdminTransactor // Write-only binding to the contract + IAdminFilterer // Log filterer for contract events +} + +// IAdminCaller is an auto generated read-only Go binding around an Ethereum contract. +type IAdminCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IAdminTransactor is an auto generated write-only Go binding around an Ethereum contract. +type IAdminTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IAdminFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IAdminFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IAdminSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type IAdminSession struct { + Contract *IAdmin // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IAdminCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type IAdminCallerSession struct { + Contract *IAdminCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// IAdminTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type IAdminTransactorSession struct { + Contract *IAdminTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IAdminRaw is an auto generated low-level Go binding around an Ethereum contract. +type IAdminRaw struct { + Contract *IAdmin // Generic contract binding to access the raw methods on +} + +// IAdminCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IAdminCallerRaw struct { + Contract *IAdminCaller // Generic read-only contract binding to access the raw methods on +} + +// IAdminTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IAdminTransactorRaw struct { + Contract *IAdminTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewIAdmin creates a new instance of IAdmin, bound to a specific deployed contract. +func NewIAdmin(address common.Address, backend bind.ContractBackend) (*IAdmin, error) { + contract, err := bindIAdmin(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &IAdmin{IAdminCaller: IAdminCaller{contract: contract}, IAdminTransactor: IAdminTransactor{contract: contract}, IAdminFilterer: IAdminFilterer{contract: contract}}, nil +} + +// NewIAdminCaller creates a new read-only instance of IAdmin, bound to a specific deployed contract. +func NewIAdminCaller(address common.Address, caller bind.ContractCaller) (*IAdminCaller, error) { + contract, err := bindIAdmin(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &IAdminCaller{contract: contract}, nil +} + +// NewIAdminTransactor creates a new write-only instance of IAdmin, bound to a specific deployed contract. +func NewIAdminTransactor(address common.Address, transactor bind.ContractTransactor) (*IAdminTransactor, error) { + contract, err := bindIAdmin(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &IAdminTransactor{contract: contract}, nil +} + +// NewIAdminFilterer creates a new log filterer instance of IAdmin, bound to a specific deployed contract. +func NewIAdminFilterer(address common.Address, filterer bind.ContractFilterer) (*IAdminFilterer, error) { + contract, err := bindIAdmin(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &IAdminFilterer{contract: contract}, nil +} + +// bindIAdmin binds a generic wrapper to an already deployed contract. +func bindIAdmin(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := IAdminMetaData.GetAbi() + if err != nil { return nil, err } - event.Raw = log - return event, nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } -// IAdminGuardAddedIterator is returned from FilterGuardAdded and is used to iterate over the raw logs and unpacked data for GuardAdded events raised by the IAdmin contract. -type IAdminGuardAddedIterator struct { - Event *IAdminGuardAdded // Event containing the contract specifics and raw log +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IAdmin *IAdminRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IAdmin.Contract.IAdminCaller.contract.Call(opts, result, method, params...) +} - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IAdmin *IAdminRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IAdmin.Contract.IAdminTransactor.contract.Transfer(opts) +} - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// Transact invokes the (paid) contract method with params as input values. +func (_IAdmin *IAdminRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IAdmin.Contract.IAdminTransactor.contract.Transact(opts, method, params...) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *IAdminGuardAddedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(IAdminGuardAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IAdmin *IAdminCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IAdmin.Contract.contract.Call(opts, result, method, params...) +} - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(IAdminGuardAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IAdmin *IAdminTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IAdmin.Contract.contract.Transfer(opts) +} - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } +// Transact invokes the (paid) contract method with params as input values. +func (_IAdmin *IAdminTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IAdmin.Contract.contract.Transact(opts, method, params...) } -// Error returns any retrieval or parsing error occurred during filtering. -func (it *IAdminGuardAddedIterator) Error() error { - return it.fail +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_IAdmin *IAdminTransactor) SetChainGasAmount(opts *bind.TransactOpts, newChainGasAmount *big.Int) (*types.Transaction, error) { + return _IAdmin.contract.Transact(opts, "setChainGasAmount", newChainGasAmount) } -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *IAdminGuardAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_IAdmin *IAdminSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { + return _IAdmin.Contract.SetChainGasAmount(&_IAdmin.TransactOpts, newChainGasAmount) } -// IAdminGuardAdded represents a GuardAdded event raised by the IAdmin contract. -type IAdminGuardAdded struct { - Guard common.Address - Raw types.Log // Blockchain specific contextual infos +// SetChainGasAmount is a paid mutator transaction binding the contract method 0xb250fe6b. +// +// Solidity: function setChainGasAmount(uint256 newChainGasAmount) returns() +func (_IAdmin *IAdminTransactorSession) SetChainGasAmount(newChainGasAmount *big.Int) (*types.Transaction, error) { + return _IAdmin.Contract.SetChainGasAmount(&_IAdmin.TransactOpts, newChainGasAmount) } -// FilterGuardAdded is a free log retrieval operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. // -// Solidity: event GuardAdded(address guard) -func (_IAdmin *IAdminFilterer) FilterGuardAdded(opts *bind.FilterOpts) (*IAdminGuardAddedIterator, error) { +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_IAdmin *IAdminTransactor) SetProtocolFeeRate(opts *bind.TransactOpts, newFeeRate *big.Int) (*types.Transaction, error) { + return _IAdmin.contract.Transact(opts, "setProtocolFeeRate", newFeeRate) +} - logs, sub, err := _IAdmin.contract.FilterLogs(opts, "GuardAdded") - if err != nil { - return nil, err - } - return &IAdminGuardAddedIterator{contract: _IAdmin.contract, event: "GuardAdded", logs: logs, sub: sub}, nil +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. +// +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_IAdmin *IAdminSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { + return _IAdmin.Contract.SetProtocolFeeRate(&_IAdmin.TransactOpts, newFeeRate) } -// WatchGuardAdded is a free log subscription operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// SetProtocolFeeRate is a paid mutator transaction binding the contract method 0xb13aa2d6. // -// Solidity: event GuardAdded(address guard) -func (_IAdmin *IAdminFilterer) WatchGuardAdded(opts *bind.WatchOpts, sink chan<- *IAdminGuardAdded) (event.Subscription, error) { +// Solidity: function setProtocolFeeRate(uint256 newFeeRate) returns() +func (_IAdmin *IAdminTransactorSession) SetProtocolFeeRate(newFeeRate *big.Int) (*types.Transaction, error) { + return _IAdmin.Contract.SetProtocolFeeRate(&_IAdmin.TransactOpts, newFeeRate) +} - logs, sub, err := _IAdmin.contract.WatchLogs(opts, "GuardAdded") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(IAdminGuardAdded) - if err := _IAdmin.contract.UnpackLog(event, "GuardAdded", log); err != nil { - return err - } - event.Raw = log +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_IAdmin *IAdminTransactor) SweepProtocolFees(opts *bind.TransactOpts, token common.Address, recipient common.Address) (*types.Transaction, error) { + return _IAdmin.contract.Transact(opts, "sweepProtocolFees", token, recipient) +} - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. +// +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_IAdmin *IAdminSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { + return _IAdmin.Contract.SweepProtocolFees(&_IAdmin.TransactOpts, token, recipient) } -// ParseGuardAdded is a log parse operation binding the contract event 0x93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f59. +// SweepProtocolFees is a paid mutator transaction binding the contract method 0x06f333f2. // -// Solidity: event GuardAdded(address guard) -func (_IAdmin *IAdminFilterer) ParseGuardAdded(log types.Log) (*IAdminGuardAdded, error) { - event := new(IAdminGuardAdded) - if err := _IAdmin.contract.UnpackLog(event, "GuardAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil +// Solidity: function sweepProtocolFees(address token, address recipient) returns() +func (_IAdmin *IAdminTransactorSession) SweepProtocolFees(token common.Address, recipient common.Address) (*types.Transaction, error) { + return _IAdmin.Contract.SweepProtocolFees(&_IAdmin.TransactOpts, token, recipient) } -// IAdminGuardRemovedIterator is returned from FilterGuardRemoved and is used to iterate over the raw logs and unpacked data for GuardRemoved events raised by the IAdmin contract. -type IAdminGuardRemovedIterator struct { - Event *IAdminGuardRemoved // Event containing the contract specifics and raw log +// IAdminChainGasAmountUpdatedIterator is returned from FilterChainGasAmountUpdated and is used to iterate over the raw logs and unpacked data for ChainGasAmountUpdated events raised by the IAdmin contract. +type IAdminChainGasAmountUpdatedIterator struct { + Event *IAdminChainGasAmountUpdated // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -13661,7 +12112,7 @@ type IAdminGuardRemovedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *IAdminGuardRemovedIterator) Next() bool { +func (it *IAdminChainGasAmountUpdatedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -13670,7 +12121,7 @@ func (it *IAdminGuardRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(IAdminGuardRemoved) + it.Event = new(IAdminChainGasAmountUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -13685,7 +12136,7 @@ func (it *IAdminGuardRemovedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(IAdminGuardRemoved) + it.Event = new(IAdminChainGasAmountUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -13701,41 +12152,42 @@ func (it *IAdminGuardRemovedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *IAdminGuardRemovedIterator) Error() error { +func (it *IAdminChainGasAmountUpdatedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *IAdminGuardRemovedIterator) Close() error { +func (it *IAdminChainGasAmountUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -// IAdminGuardRemoved represents a GuardRemoved event raised by the IAdmin contract. -type IAdminGuardRemoved struct { - Guard common.Address - Raw types.Log // Blockchain specific contextual infos +// IAdminChainGasAmountUpdated represents a ChainGasAmountUpdated event raised by the IAdmin contract. +type IAdminChainGasAmountUpdated struct { + OldChainGasAmount *big.Int + NewChainGasAmount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterGuardRemoved is a free log retrieval operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// FilterChainGasAmountUpdated is a free log retrieval operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event GuardRemoved(address guard) -func (_IAdmin *IAdminFilterer) FilterGuardRemoved(opts *bind.FilterOpts) (*IAdminGuardRemovedIterator, error) { +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_IAdmin *IAdminFilterer) FilterChainGasAmountUpdated(opts *bind.FilterOpts) (*IAdminChainGasAmountUpdatedIterator, error) { - logs, sub, err := _IAdmin.contract.FilterLogs(opts, "GuardRemoved") + logs, sub, err := _IAdmin.contract.FilterLogs(opts, "ChainGasAmountUpdated") if err != nil { return nil, err } - return &IAdminGuardRemovedIterator{contract: _IAdmin.contract, event: "GuardRemoved", logs: logs, sub: sub}, nil + return &IAdminChainGasAmountUpdatedIterator{contract: _IAdmin.contract, event: "ChainGasAmountUpdated", logs: logs, sub: sub}, nil } -// WatchGuardRemoved is a free log subscription operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// WatchChainGasAmountUpdated is a free log subscription operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event GuardRemoved(address guard) -func (_IAdmin *IAdminFilterer) WatchGuardRemoved(opts *bind.WatchOpts, sink chan<- *IAdminGuardRemoved) (event.Subscription, error) { +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_IAdmin *IAdminFilterer) WatchChainGasAmountUpdated(opts *bind.WatchOpts, sink chan<- *IAdminChainGasAmountUpdated) (event.Subscription, error) { - logs, sub, err := _IAdmin.contract.WatchLogs(opts, "GuardRemoved") + logs, sub, err := _IAdmin.contract.WatchLogs(opts, "ChainGasAmountUpdated") if err != nil { return nil, err } @@ -13745,8 +12197,8 @@ func (_IAdmin *IAdminFilterer) WatchGuardRemoved(opts *bind.WatchOpts, sink chan select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(IAdminGuardRemoved) - if err := _IAdmin.contract.UnpackLog(event, "GuardRemoved", log); err != nil { + event := new(IAdminChainGasAmountUpdated) + if err := _IAdmin.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { return err } event.Raw = log @@ -13767,21 +12219,21 @@ func (_IAdmin *IAdminFilterer) WatchGuardRemoved(opts *bind.WatchOpts, sink chan }), nil } -// ParseGuardRemoved is a log parse operation binding the contract event 0x59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d048. +// ParseChainGasAmountUpdated is a log parse operation binding the contract event 0x5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa. // -// Solidity: event GuardRemoved(address guard) -func (_IAdmin *IAdminFilterer) ParseGuardRemoved(log types.Log) (*IAdminGuardRemoved, error) { - event := new(IAdminGuardRemoved) - if err := _IAdmin.contract.UnpackLog(event, "GuardRemoved", log); err != nil { +// Solidity: event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount) +func (_IAdmin *IAdminFilterer) ParseChainGasAmountUpdated(log types.Log) (*IAdminChainGasAmountUpdated, error) { + event := new(IAdminChainGasAmountUpdated) + if err := _IAdmin.contract.UnpackLog(event, "ChainGasAmountUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -// IAdminRelayerAddedIterator is returned from FilterRelayerAdded and is used to iterate over the raw logs and unpacked data for RelayerAdded events raised by the IAdmin contract. -type IAdminRelayerAddedIterator struct { - Event *IAdminRelayerAdded // Event containing the contract specifics and raw log +// IAdminFeeRateUpdatedIterator is returned from FilterFeeRateUpdated and is used to iterate over the raw logs and unpacked data for FeeRateUpdated events raised by the IAdmin contract. +type IAdminFeeRateUpdatedIterator struct { + Event *IAdminFeeRateUpdated // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -13795,7 +12247,7 @@ type IAdminRelayerAddedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *IAdminRelayerAddedIterator) Next() bool { +func (it *IAdminFeeRateUpdatedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -13804,7 +12256,7 @@ func (it *IAdminRelayerAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(IAdminRelayerAdded) + it.Event = new(IAdminFeeRateUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -13819,7 +12271,7 @@ func (it *IAdminRelayerAddedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(IAdminRelayerAdded) + it.Event = new(IAdminFeeRateUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -13835,41 +12287,42 @@ func (it *IAdminRelayerAddedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *IAdminRelayerAddedIterator) Error() error { +func (it *IAdminFeeRateUpdatedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *IAdminRelayerAddedIterator) Close() error { +func (it *IAdminFeeRateUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -// IAdminRelayerAdded represents a RelayerAdded event raised by the IAdmin contract. -type IAdminRelayerAdded struct { - Relayer common.Address - Raw types.Log // Blockchain specific contextual infos +// IAdminFeeRateUpdated represents a FeeRateUpdated event raised by the IAdmin contract. +type IAdminFeeRateUpdated struct { + OldFeeRate *big.Int + NewFeeRate *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterRelayerAdded is a free log retrieval operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// FilterFeeRateUpdated is a free log retrieval operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. // -// Solidity: event RelayerAdded(address relayer) -func (_IAdmin *IAdminFilterer) FilterRelayerAdded(opts *bind.FilterOpts) (*IAdminRelayerAddedIterator, error) { +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_IAdmin *IAdminFilterer) FilterFeeRateUpdated(opts *bind.FilterOpts) (*IAdminFeeRateUpdatedIterator, error) { - logs, sub, err := _IAdmin.contract.FilterLogs(opts, "RelayerAdded") + logs, sub, err := _IAdmin.contract.FilterLogs(opts, "FeeRateUpdated") if err != nil { return nil, err } - return &IAdminRelayerAddedIterator{contract: _IAdmin.contract, event: "RelayerAdded", logs: logs, sub: sub}, nil + return &IAdminFeeRateUpdatedIterator{contract: _IAdmin.contract, event: "FeeRateUpdated", logs: logs, sub: sub}, nil } -// WatchRelayerAdded is a free log subscription operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// WatchFeeRateUpdated is a free log subscription operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. // -// Solidity: event RelayerAdded(address relayer) -func (_IAdmin *IAdminFilterer) WatchRelayerAdded(opts *bind.WatchOpts, sink chan<- *IAdminRelayerAdded) (event.Subscription, error) { +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_IAdmin *IAdminFilterer) WatchFeeRateUpdated(opts *bind.WatchOpts, sink chan<- *IAdminFeeRateUpdated) (event.Subscription, error) { - logs, sub, err := _IAdmin.contract.WatchLogs(opts, "RelayerAdded") + logs, sub, err := _IAdmin.contract.WatchLogs(opts, "FeeRateUpdated") if err != nil { return nil, err } @@ -13879,8 +12332,8 @@ func (_IAdmin *IAdminFilterer) WatchRelayerAdded(opts *bind.WatchOpts, sink chan select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(IAdminRelayerAdded) - if err := _IAdmin.contract.UnpackLog(event, "RelayerAdded", log); err != nil { + event := new(IAdminFeeRateUpdated) + if err := _IAdmin.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { return err } event.Raw = log @@ -13901,21 +12354,21 @@ func (_IAdmin *IAdminFilterer) WatchRelayerAdded(opts *bind.WatchOpts, sink chan }), nil } -// ParseRelayerAdded is a log parse operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// ParseFeeRateUpdated is a log parse operation binding the contract event 0x14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb957. // -// Solidity: event RelayerAdded(address relayer) -func (_IAdmin *IAdminFilterer) ParseRelayerAdded(log types.Log) (*IAdminRelayerAdded, error) { - event := new(IAdminRelayerAdded) - if err := _IAdmin.contract.UnpackLog(event, "RelayerAdded", log); err != nil { +// Solidity: event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate) +func (_IAdmin *IAdminFilterer) ParseFeeRateUpdated(log types.Log) (*IAdminFeeRateUpdated, error) { + event := new(IAdminFeeRateUpdated) + if err := _IAdmin.contract.UnpackLog(event, "FeeRateUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -// IAdminRelayerRemovedIterator is returned from FilterRelayerRemoved and is used to iterate over the raw logs and unpacked data for RelayerRemoved events raised by the IAdmin contract. -type IAdminRelayerRemovedIterator struct { - Event *IAdminRelayerRemoved // Event containing the contract specifics and raw log +// IAdminFeesSweptIterator is returned from FilterFeesSwept and is used to iterate over the raw logs and unpacked data for FeesSwept events raised by the IAdmin contract. +type IAdminFeesSweptIterator struct { + Event *IAdminFeesSwept // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -13929,7 +12382,7 @@ type IAdminRelayerRemovedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *IAdminRelayerRemovedIterator) Next() bool { +func (it *IAdminFeesSweptIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -13938,7 +12391,7 @@ func (it *IAdminRelayerRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(IAdminRelayerRemoved) + it.Event = new(IAdminFeesSwept) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -13953,7 +12406,7 @@ func (it *IAdminRelayerRemovedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(IAdminRelayerRemoved) + it.Event = new(IAdminFeesSwept) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -13969,41 +12422,43 @@ func (it *IAdminRelayerRemovedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *IAdminRelayerRemovedIterator) Error() error { +func (it *IAdminFeesSweptIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *IAdminRelayerRemovedIterator) Close() error { +func (it *IAdminFeesSweptIterator) Close() error { it.sub.Unsubscribe() return nil } -// IAdminRelayerRemoved represents a RelayerRemoved event raised by the IAdmin contract. -type IAdminRelayerRemoved struct { - Relayer common.Address - Raw types.Log // Blockchain specific contextual infos +// IAdminFeesSwept represents a FeesSwept event raised by the IAdmin contract. +type IAdminFeesSwept struct { + Token common.Address + Recipient common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterRelayerRemoved is a free log retrieval operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// FilterFeesSwept is a free log retrieval operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. // -// Solidity: event RelayerRemoved(address relayer) -func (_IAdmin *IAdminFilterer) FilterRelayerRemoved(opts *bind.FilterOpts) (*IAdminRelayerRemovedIterator, error) { +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_IAdmin *IAdminFilterer) FilterFeesSwept(opts *bind.FilterOpts) (*IAdminFeesSweptIterator, error) { - logs, sub, err := _IAdmin.contract.FilterLogs(opts, "RelayerRemoved") + logs, sub, err := _IAdmin.contract.FilterLogs(opts, "FeesSwept") if err != nil { return nil, err } - return &IAdminRelayerRemovedIterator{contract: _IAdmin.contract, event: "RelayerRemoved", logs: logs, sub: sub}, nil + return &IAdminFeesSweptIterator{contract: _IAdmin.contract, event: "FeesSwept", logs: logs, sub: sub}, nil } -// WatchRelayerRemoved is a free log subscription operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// WatchFeesSwept is a free log subscription operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. // -// Solidity: event RelayerRemoved(address relayer) -func (_IAdmin *IAdminFilterer) WatchRelayerRemoved(opts *bind.WatchOpts, sink chan<- *IAdminRelayerRemoved) (event.Subscription, error) { +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_IAdmin *IAdminFilterer) WatchFeesSwept(opts *bind.WatchOpts, sink chan<- *IAdminFeesSwept) (event.Subscription, error) { - logs, sub, err := _IAdmin.contract.WatchLogs(opts, "RelayerRemoved") + logs, sub, err := _IAdmin.contract.WatchLogs(opts, "FeesSwept") if err != nil { return nil, err } @@ -14013,8 +12468,8 @@ func (_IAdmin *IAdminFilterer) WatchRelayerRemoved(opts *bind.WatchOpts, sink ch select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(IAdminRelayerRemoved) - if err := _IAdmin.contract.UnpackLog(event, "RelayerRemoved", log); err != nil { + event := new(IAdminFeesSwept) + if err := _IAdmin.contract.UnpackLog(event, "FeesSwept", log); err != nil { return err } event.Raw = log @@ -14035,12 +12490,12 @@ func (_IAdmin *IAdminFilterer) WatchRelayerRemoved(opts *bind.WatchOpts, sink ch }), nil } -// ParseRelayerRemoved is a log parse operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// ParseFeesSwept is a log parse operation binding the contract event 0x244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd. // -// Solidity: event RelayerRemoved(address relayer) -func (_IAdmin *IAdminFilterer) ParseRelayerRemoved(log types.Log) (*IAdminRelayerRemoved, error) { - event := new(IAdminRelayerRemoved) - if err := _IAdmin.contract.UnpackLog(event, "RelayerRemoved", log); err != nil { +// Solidity: event FeesSwept(address token, address recipient, uint256 amount) +func (_IAdmin *IAdminFilterer) ParseFeesSwept(log types.Log) (*IAdminFeesSwept, error) { + event := new(IAdminFeesSwept) + if err := _IAdmin.contract.UnpackLog(event, "FeesSwept", log); err != nil { return nil, err } event.Raw = log @@ -16416,7 +14871,7 @@ func (_IFastBridge *IFastBridgeFilterer) ParseBridgeRequested(log types.Log) (*I // SafeERC20MetaData contains all meta data concerning the SafeERC20 contract. var SafeERC20MetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"currentAllowance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestedDecrease\",\"type\":\"uint256\"}],\"name\":\"SafeERC20FailedDecreaseAllowance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"}]", - Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212205eb4e090a6f6b36dc901d60cd1bbcfc48c2db77de14c95f950ce0b9585cba21f64736f6c63430008140033", + Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c51b222f1984df769e9e9836d8b17da22ec98bfb801c9728e848da279f2ef33e64736f6c63430008140033", } // SafeERC20ABI is the input ABI used to generate the binding from. @@ -16589,7 +15044,7 @@ func (_SafeERC20 *SafeERC20TransactorRaw) Transact(opts *bind.TransactOpts, meth // UniversalTokenLibMetaData contains all meta data concerning the UniversalTokenLib contract. var UniversalTokenLibMetaData = &bind.MetaData{ ABI: "[]", - Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212208c262359b6648f7f4b885113d3ee31cd52f290219086243f6a491efdf608653264736f6c63430008140033", + Bin: "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220091110fff57e33a0f49e1afe323fd28b79984a963c9cb8afaca914399291e9a964736f6c63430008140033", } // UniversalTokenLibABI is the input ABI used to generate the binding from. diff --git a/services/rfq/contracts/testcontracts/fastbridgemock/fastbridgemock.contractinfo.json b/services/rfq/contracts/testcontracts/fastbridgemock/fastbridgemock.contractinfo.json index 28915476a8..778e6fee04 100644 --- a/services/rfq/contracts/testcontracts/fastbridgemock/fastbridgemock.contractinfo.json +++ b/services/rfq/contracts/testcontracts/fastbridgemock/fastbridgemock.contractinfo.json @@ -1 +1 @@ -{"solidity/FastBridgeMock.sol:AccessControl":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n ) external {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Contract module that allows children to implement role-based access control mechanisms. This is a lightweight version that doesn't allow enumerating role members except through off-chain means by accessing the contract event logs. Some applications may benefit from on-chain enumerability, for those cases see {AccessControlEnumerable}. Roles are referred to by their `bytes32` identifier. These should be exposed in the external API and be unique. The best way to achieve this is by using `public constant` hash digests: ```solidity bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\"); ``` Roles can be used to represent a set of permissions. To restrict access to a function call, use {hasRole}: ```solidity function foo() public { require(hasRole(MY_ROLE, msg.sender)); ... } ``` Roles can be granted and revoked dynamically via the {grantRole} and {revokeRole} functions. Each role has an associated admin role, and only accounts that have a role's admin role can call {grantRole} and {revokeRole}. By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using {_setRoleAdmin}. WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} to enforce additional security measures for this role.","errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Contract module that allows children to implement role-based access control mechanisms. This is a lightweight version that doesn't allow enumerating role members except through off-chain means by accessing the contract event logs. Some applications may benefit from on-chain enumerability, for those cases see {AccessControlEnumerable}. Roles are referred to by their `bytes32` identifier. These should be exposed in the external API and be unique. The best way to achieve this is by using `public constant` hash digests: ```solidity bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\"); ``` Roles can be used to represent a set of permissions. To restrict access to a function call, use {hasRole}: ```solidity function foo() public { require(hasRole(MY_ROLE, msg.sender)); ... } ``` Roles can be granted and revoked dynamically via the {grantRole} and {revokeRole} functions. Each role has an associated admin role, and only accounts that have a role's admin role can call {grantRole} and {revokeRole}. By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using {_setRoleAdmin}. WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} to enforce additional security measures for this role.\",\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"AccessControl\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0xfdd0a71cdd1fe45137a59bc8e7544699eb71ead398af2fd0f1cf448a878ccacd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://07ce767dbb21de80ca0b546310d3c374ed7ddcf5376c7085f15c7812f7678819\",\"dweb:/ipfs/QmQ3JUoivC7YRSxZnRstRKmJJ8x8cLLhEbgWsiXV5NmYrs\"]}},\"version\":1}"},"hashes":{"DEFAULT_ADMIN_ROLE()":"a217fddf","getRoleAdmin(bytes32)":"248a9ca3","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","supportsInterface(bytes4)":"01ffc9a7"}},"solidity/FastBridgeMock.sol:Address":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122017364e1ba957198b5cc9fefb513c6037bd8284eb81dd4aa2302b849eec9d9d5364736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122017364e1ba957198b5cc9fefb513c6037bd8284eb81dd4aa2302b849eec9d9d5364736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n ) external {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"16176:6066:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;16176:6066:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"16176:6066:0:-:0;;;;;;;;","abiDefinition":[{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Collection of functions related to the address type","errors":{"AddressEmptyCode(address)":[{"details":"There's no code at `target` (it is not a contract)."}],"AddressInsufficientBalance(address)":[{"details":"The ETH balance of the account is not enough to perform the operation."}],"FailedInnerCall()":[{"details":"A call to an address target failed. The target may have reverted."}]},"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"}],\"devdoc\":{\"details\":\"Collection of functions related to the address type\",\"errors\":{\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"AddressInsufficientBalance(address)\":[{\"details\":\"The ETH balance of the account is not enough to perform the operation.\"}],\"FailedInnerCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}]},\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"Address\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0xfdd0a71cdd1fe45137a59bc8e7544699eb71ead398af2fd0f1cf448a878ccacd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://07ce767dbb21de80ca0b546310d3c374ed7ddcf5376c7085f15c7812f7678819\",\"dweb:/ipfs/QmQ3JUoivC7YRSxZnRstRKmJJ8x8cLLhEbgWsiXV5NmYrs\"]}},\"version\":1}"},"hashes":{}},"solidity/FastBridgeMock.sol:Admin":{"code":"0x608060405234801561001057600080fd5b50604051620015cf380380620015cf833981016040819052610031916100ef565b61003c600082610043565b505061011f565b6000828152602081815260408083206001600160a01b038516845290915281205460ff166100e5576000838152602081815260408083206001600160a01b03861684529091529020805460ff1916600117905561009d3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016100e9565b5060005b92915050565b60006020828403121561010157600080fd5b81516001600160a01b038116811461011857600080fd5b9392505050565b6114a0806200012f6000396000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c8063926d7d7f116100e3578063ccc574901161008c578063dd39f00d11610066578063dd39f00d146103b3578063e00a83e0146103c6578063eecdac88146103cf57600080fd5b8063ccc5749014610359578063d547741f14610380578063dcf844a71461039357600080fd5b8063b250fe6b116100bd578063b250fe6b14610329578063b62350161461033c578063bf333f2c1461034f57600080fd5b8063926d7d7f146102e7578063a217fddf1461030e578063b13aa2d61461031657600080fd5b806336568abe1161014557806360f0a5ac1161011f57806360f0a5ac1461027d5780636913a63c1461029057806391d14854146102a357600080fd5b806336568abe1461024e5780633c4a25d01461026157806358f858801461027457600080fd5b80630f5f6ed7116101765780630f5f6ed71461020f578063248a9ca3146102185780632f2ff15d1461023b57600080fd5b806301ffc9a71461019d57806303ed0ee5146101c557806306f333f2146101fa575b600080fd5b6101b06101ab366004611324565b6103e2565b60405190151581526020015b60405180910390f35b6101ec7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b6040519081526020016101bc565b61020d61020836600461138f565b61047b565b005b6101ec61271081565b6101ec6102263660046113c2565b60009081526020819052604090206001015490565b61020d6102493660046113db565b6105da565b61020d61025c3660046113db565b610605565b61020d61026f3660046113fe565b610663565b6101ec60015481565b61020d61028b3660046113fe565b610716565b61020d61029e3660046113fe565b6107c2565b6101b06102b13660046113db565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6101ec7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b6101ec600081565b61020d6103243660046113c2565b61086e565b61020d6103373660046113c2565b6109b8565b61020d61034a3660046113fe565b610a8e565b6101ec620f424081565b6101ec7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b61020d61038e3660046113db565b610b3a565b6101ec6103a13660046113fe565b60026020526000908152604090205481565b61020d6103c13660046113fe565b610b5f565b6101ec60035481565b61020d6103dd3660046113fe565b610c0b565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061047557507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16610518576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600260205260408120549081900361054b57505050565b73ffffffffffffffffffffffffffffffffffffffff831660008181526002602052604081205561057c908383610cb7565b6040805173ffffffffffffffffffffffffffffffffffffffff8086168252841660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b5050565b6000828152602081905260409020600101546105f581610e0e565b6105ff8383610e1b565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610654576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61065e8282610f17565b505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661069e57600080fd5b6106c87f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5582610e1b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5906020015b60405180910390a150565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661075157600080fd5b61077b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc482610f17565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b9060200161070b565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166107fd57600080fd5b6108277f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d82610e1b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f599060200161070b565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16610906576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f720000000000000000604482015260640161050f565b612710811115610972576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d617800000000000000000000000000000000604482015260640161050f565b600180549082905560408051828152602081018490527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a15050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16610a50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f720000000000000000604482015260640161050f565b600380549082905560408051828152602081018490527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa91016109ac565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610ac957600080fd5b610af37f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d82610f17565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d0489060200161070b565b600082815260208190526040902060010154610b5581610e0e565b6105ff8383610f17565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610b9a57600080fd5b610bc47fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc482610e1b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c59060200161070b565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610c4657600080fd5b610c707f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5582610f17565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b9060200161070b565b3073ffffffffffffffffffffffffffffffffffffffff831603610cd957505050565b80600003610ce657505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff841601610ded5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610d7d576040519150601f19603f3d011682016040523d82523d6000602084013e610d82565b606091505b50509050806105ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c656400000000000000000000000000604482015260640161050f565b61065e73ffffffffffffffffffffffffffffffffffffffff84168383610fd2565b610e18813361105f565b50565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16610f0f5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610ead3390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610475565b506000610475565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff1615610f0f5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610475565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261065e9084906110e5565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166105d6576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024810183905260440161050f565b600061110773ffffffffffffffffffffffffffffffffffffffff84168361117b565b9050805160001415801561112c57508080602001905181019061112a9190611419565b155b1561065e576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161050f565b606061118983836000611190565b9392505050565b6060814710156111ce576040517fcd78605900000000000000000000000000000000000000000000000000000000815230600482015260240161050f565b6000808573ffffffffffffffffffffffffffffffffffffffff1684866040516111f7919061143b565b60006040518083038185875af1925050503d8060008114611234576040519150601f19603f3d011682016040523d82523d6000602084013e611239565b606091505b5091509150611249868383611253565b9695505050505050565b60608261126857611263826112e2565b611189565b815115801561128c575073ffffffffffffffffffffffffffffffffffffffff84163b155b156112db576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015260240161050f565b5080611189565b8051156112f25780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561133657600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461118957600080fd5b803573ffffffffffffffffffffffffffffffffffffffff8116811461138a57600080fd5b919050565b600080604083850312156113a257600080fd5b6113ab83611366565b91506113b960208401611366565b90509250929050565b6000602082840312156113d457600080fd5b5035919050565b600080604083850312156113ee57600080fd5b823591506113b960208401611366565b60006020828403121561141057600080fd5b61118982611366565b60006020828403121561142b57600080fd5b8151801515811461118957600080fd5b6000825160005b8181101561145c5760208186018101518583015201611442565b50600092019182525091905056fea26469706673582212205c49afb355dff0d97bec5b816fcda1abe23f00447ca3f7d7a753997929922bba64736f6c63430008140033","runtime-code":"0x608060405234801561001057600080fd5b50600436106101985760003560e01c8063926d7d7f116100e3578063ccc574901161008c578063dd39f00d11610066578063dd39f00d146103b3578063e00a83e0146103c6578063eecdac88146103cf57600080fd5b8063ccc5749014610359578063d547741f14610380578063dcf844a71461039357600080fd5b8063b250fe6b116100bd578063b250fe6b14610329578063b62350161461033c578063bf333f2c1461034f57600080fd5b8063926d7d7f146102e7578063a217fddf1461030e578063b13aa2d61461031657600080fd5b806336568abe1161014557806360f0a5ac1161011f57806360f0a5ac1461027d5780636913a63c1461029057806391d14854146102a357600080fd5b806336568abe1461024e5780633c4a25d01461026157806358f858801461027457600080fd5b80630f5f6ed7116101765780630f5f6ed71461020f578063248a9ca3146102185780632f2ff15d1461023b57600080fd5b806301ffc9a71461019d57806303ed0ee5146101c557806306f333f2146101fa575b600080fd5b6101b06101ab366004611324565b6103e2565b60405190151581526020015b60405180910390f35b6101ec7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b6040519081526020016101bc565b61020d61020836600461138f565b61047b565b005b6101ec61271081565b6101ec6102263660046113c2565b60009081526020819052604090206001015490565b61020d6102493660046113db565b6105da565b61020d61025c3660046113db565b610605565b61020d61026f3660046113fe565b610663565b6101ec60015481565b61020d61028b3660046113fe565b610716565b61020d61029e3660046113fe565b6107c2565b6101b06102b13660046113db565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6101ec7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b6101ec600081565b61020d6103243660046113c2565b61086e565b61020d6103373660046113c2565b6109b8565b61020d61034a3660046113fe565b610a8e565b6101ec620f424081565b6101ec7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b61020d61038e3660046113db565b610b3a565b6101ec6103a13660046113fe565b60026020526000908152604090205481565b61020d6103c13660046113fe565b610b5f565b6101ec60035481565b61020d6103dd3660046113fe565b610c0b565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061047557507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16610518576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600260205260408120549081900361054b57505050565b73ffffffffffffffffffffffffffffffffffffffff831660008181526002602052604081205561057c908383610cb7565b6040805173ffffffffffffffffffffffffffffffffffffffff8086168252841660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b5050565b6000828152602081905260409020600101546105f581610e0e565b6105ff8383610e1b565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610654576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61065e8282610f17565b505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661069e57600080fd5b6106c87f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5582610e1b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5906020015b60405180910390a150565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661075157600080fd5b61077b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc482610f17565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b9060200161070b565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166107fd57600080fd5b6108277f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d82610e1b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f599060200161070b565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16610906576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f720000000000000000604482015260640161050f565b612710811115610972576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d617800000000000000000000000000000000604482015260640161050f565b600180549082905560408051828152602081018490527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a15050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16610a50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f720000000000000000604482015260640161050f565b600380549082905560408051828152602081018490527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa91016109ac565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610ac957600080fd5b610af37f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d82610f17565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d0489060200161070b565b600082815260208190526040902060010154610b5581610e0e565b6105ff8383610f17565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610b9a57600080fd5b610bc47fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc482610e1b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c59060200161070b565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610c4657600080fd5b610c707f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5582610f17565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b9060200161070b565b3073ffffffffffffffffffffffffffffffffffffffff831603610cd957505050565b80600003610ce657505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff841601610ded5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610d7d576040519150601f19603f3d011682016040523d82523d6000602084013e610d82565b606091505b50509050806105ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c656400000000000000000000000000604482015260640161050f565b61065e73ffffffffffffffffffffffffffffffffffffffff84168383610fd2565b610e18813361105f565b50565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16610f0f5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610ead3390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610475565b506000610475565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff1615610f0f5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610475565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261065e9084906110e5565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166105d6576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024810183905260440161050f565b600061110773ffffffffffffffffffffffffffffffffffffffff84168361117b565b9050805160001415801561112c57508080602001905181019061112a9190611419565b155b1561065e576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161050f565b606061118983836000611190565b9392505050565b6060814710156111ce576040517fcd78605900000000000000000000000000000000000000000000000000000000815230600482015260240161050f565b6000808573ffffffffffffffffffffffffffffffffffffffff1684866040516111f7919061143b565b60006040518083038185875af1925050503d8060008114611234576040519150601f19603f3d011682016040523d82523d6000602084013e611239565b606091505b5091509150611249868383611253565b9695505050505050565b60608261126857611263826112e2565b611189565b815115801561128c575073ffffffffffffffffffffffffffffffffffffffff84163b155b156112db576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015260240161050f565b5080611189565b8051156112f25780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561133657600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461118957600080fd5b803573ffffffffffffffffffffffffffffffffffffffff8116811461138a57600080fd5b919050565b600080604083850312156113a257600080fd5b6113ab83611366565b91506113b960208401611366565b90509250929050565b6000602082840312156113d457600080fd5b5035919050565b600080604083850312156113ee57600080fd5b823591506113b960208401611366565b60006020828403121561141057600080fd5b61118982611366565b60006020828403121561142b57600080fd5b8151801515811461118957600080fd5b6000825160005b8181101561145c5760208186018101518583015201611442565b50600092019182525091905056fea26469706673582212205c49afb355dff0d97bec5b816fcda1abe23f00447ca3f7d7a753997929922bba64736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n ) external {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"40134:3303:0:-:0;;;41254:83;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41292:38;32700:4;41323:6;41292:10;:38::i;:::-;;41254:83;40134:3303;;36647:316;36724:4;33422:12;;;;;;;;;;;-1:-1:-1;;;;;33422:29:0;;;;;;;;;;;;36740:217;;36783:6;:12;;;;;;;;;;;-1:-1:-1;;;;;36783:29:0;;;;;;;;;:36;;-1:-1:-1;;36783:36:0;36815:4;36783:36;;;36865:12;22980:10;;22901:96;36865:12;-1:-1:-1;;;;;36838:40:0;36856:7;-1:-1:-1;;;;;36838:40:0;36850:4;36838:40;;;;;;;;;;-1:-1:-1;36899:4:0;36892:11;;36740:217;-1:-1:-1;36941:5:0;36740:217;36647:316;;;;:::o;14:290:1:-;84:6;137:2;125:9;116:7;112:23;108:32;105:52;;;153:1;150;143:12;105:52;179:16;;-1:-1:-1;;;;;224:31:1;;214:42;;204:70;;270:1;267;260:12;204:70;293:5;14:290;-1:-1:-1;;;14:290:1:o;:::-;40134:3303:0;;;;;;","srcMapRuntime":"40134:3303:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33033:202;;;;;;:::i;:::-;;:::i;:::-;;;516:14:1;;509:22;491:41;;479:2;464:18;33033:202:0;;;;;;;;40292:60;;40329:23;40292:60;;;;;689:25:1;;;677:2;662:18;40292:60:0;543:177:1;42828:348:0;;;;;;:::i;:::-;;:::i;:::-;;40474:45;;40513:6;40474:45;;34278:120;;;;;;:::i;:::-;34343:7;34369:12;;;;;;;;;;:22;;;;34278:120;34694:136;;;;;;:::i;:::-;;:::i;35796:245::-;;;;;;:::i;:::-;;:::i;42127:199::-;;;;;;:::i;:::-;;:::i;40636:30::-;;;;;;41542:199;;;;;;:::i;:::-;;:::i;41747:181::-;;;;;;:::i;:::-;;:::i;33322:136::-;;;;;;:::i;:::-;33399:4;33422:12;;;;;;;;;;;:29;;;;;;;;;;;;;;;;33322:136;40222:64;;40261:25;40222:64;;32655:49;;32700:4;32655:49;;42543:279;;;;;;:::i;:::-;;:::i;43182:253::-;;;;;;:::i;:::-;;:::i;41934:187::-;;;;;;:::i;:::-;;:::i;40431:37::-;;40465:3;40431:37;;40358:66;;40398:26;40358:66;;35110:138;;;;;;:::i;:::-;;:::i;40722:47::-;;;;;;:::i;:::-;;;;;;;;;;;;;;41343:193;;;;;;:::i;:::-;;:::i;40843:29::-;;;;;;42332:205;;;;;;:::i;:::-;;:::i;33033:202::-;33118:4;33141:47;;;33156:32;33141:47;;:87;;-1:-1:-1;24946:25:0;24931:40;;;;33192:36;33134:94;33033:202;-1:-1:-1;;33033:202:0:o;42828:348::-;41190:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41159:71;;;;;;;2395:2:1;41159:71:0;;;2377:21:1;2434:2;2414:18;;;2407:30;2473:26;2453:18;;;2446:54;2517:18;;41159:71:0;;;;;;;;;42941:19:::1;::::0;::::1;42921:17;42941:19:::0;;;:12:::1;:19;::::0;;;;;;42974:14;;;42970:27:::1;;42990:7;42828:348:::0;;:::o;42970:27::-:1;43038:19;::::0;::::1;43060:1;43038:19:::0;;;:12:::1;:19;::::0;;;;:23;43071:45:::1;::::0;43095:9;43106;43071:23:::1;:45::i;:::-;43131:38;::::0;;2758:42:1;2827:15;;;2809:34;;2879:15;;2874:2;2859:18;;2852:43;2911:18;;;2904:34;;;43131:38:0::1;::::0;2736:2:1;2721:18;43131:38:0::1;;;;;;;42911:265;41240:1;42828:348:::0;;:::o;34694:136::-;34343:7;34369:12;;;;;;;;;;:22;;;32932:16;32943:4;32932:10;:16::i;:::-;34798:25:::1;34809:4;34815:7;34798:10;:25::i;:::-;;34694:136:::0;;;:::o;35796:245::-;35889:34;;;22980:10;35889:34;35885:102;;35946:30;;;;;;;;;;;;;;35885:102;35997:37;36009:4;36015:18;35997:11;:37::i;:::-;;35796:245;;:::o;42127:199::-;42222:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;42186:48;;;;;;42244:36;40398:26;42270:9;42244:10;:36::i;:::-;-1:-1:-1;42295:24:0;;3125:42:1;3113:55;;3095:74;;42295:24:0;;3083:2:1;3068:18;42295:24:0;;;;;;;;42127:199;:::o;41542:::-;41638:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41602:48;;;;;;41660:35;40261:25;41686:8;41660:11;:35::i;:::-;-1:-1:-1;41710:24:0;;3125:42:1;3113:55;;3095:74;;41710:24:0;;3083:2:1;3068:18;41710:24:0;2949:226:1;41747:181:0;41836:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41800:48;;;;;;41858:30;40329:23;41881:6;41858:10;:30::i;:::-;-1:-1:-1;41903:18:0;;3125:42:1;3113:55;;3095:74;;41903:18:0;;3083:2:1;3068:18;41903::0;2949:226:1;42543:279:0;41190:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41159:71;;;;;;;2395:2:1;41159:71:0;;;2377:21:1;2434:2;2414:18;;;2407:30;2473:26;2453:18;;;2446:54;2517:18;;41159:71:0;2193:348:1;41159:71:0;40513:6:::1;42631:10;:26;;42623:55;;;::::0;::::1;::::0;;3382:2:1;42623:55:0::1;::::0;::::1;3364:21:1::0;3421:2;3401:18;;;3394:30;3460:18;3440;;;3433:46;3496:18;;42623:55:0::1;3180:340:1::0;42623:55:0::1;42709:15;::::0;;42734:28;;;;42777:38:::1;::::0;;3699:25:1;;;3755:2;3740:18;;3733:34;;;42777:38:0::1;::::0;3672:18:1;42777:38:0::1;;;;;;;;42613:209;42543:279:::0;:::o;43182:253::-;41190:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41159:71;;;;;;;2395:2:1;41159:71:0;;;2377:21:1;2434:2;2414:18;;;2407:30;2473:26;2453:18;;;2446:54;2517:18;;41159:71:0;2193:348:1;41159:71:0;43296:14:::1;::::0;;43320:34;;;;43369:59:::1;::::0;;3699:25:1;;;3755:2;3740:18;;3733:34;;;43369:59:0::1;::::0;3672:18:1;43369:59:0::1;3525:248:1::0;41934:187:0;42026:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41990:48;;;;;;42048:31;40329:23;42072:6;42048:11;:31::i;:::-;-1:-1:-1;42094:20:0;;3125:42:1;3113:55;;3095:74;;42094:20:0;;3083:2:1;3068:18;42094:20:0;2949:226:1;35110:138:0;34343:7;34369:12;;;;;;;;;;:22;;;32932:16;32943:4;32932:10;:16::i;:::-;35215:26:::1;35227:4;35233:7;35215:11;:26::i;41343:193::-:0;41436:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41400:48;;;;;;41458:34;40261:25;41483:8;41458:10;:34::i;:::-;-1:-1:-1;41507:22:0;;3125:42:1;3113:55;;3095:74;;41507:22:0;;3083:2:1;3068:18;41507:22:0;2949:226:1;42332:205:0;42430:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;42394:48;;;;;;42452:37;40398:26;42479:9;42452:11;:37::i;:::-;-1:-1:-1;42504:26:0;;3125:42:1;3113:55;;3095:74;;42504:26:0;;3083:2:1;3068:18;42504:26:0;2949:226:1;37945:653:0;38120:4;38106:19;;;;38102:32;;37945:653;;;:::o;38102:32::-;38206:5;38215:1;38206:10;38202:23;;37945:653;;;:::o;38202:23::-;38238:20;;;;;38234:358;;38418:12;38435:2;:7;;38450:5;38435:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38417:43;;;38482:7;38474:39;;;;;;;4190:2:1;38474:39:0;;;4172:21:1;4229:2;4209:18;;;4202:30;4268:21;4248:18;;;4241:49;4307:18;;38474:39:0;3988:343:1;38234:358:0;38544:37;:26;;;38571:2;38575:5;38544:26;:37::i;33667:103::-;33733:30;33744:4;22980:10;33733;:30::i;:::-;33667:103;:::o;36647:316::-;36724:4;33422:12;;;;;;;;;;;:29;;;;;;;;;;;;;36740:217;;36783:6;:12;;;;;;;;;;;:29;;;;;;;;;;:36;;;;36815:4;36783:36;;;36865:12;22980:10;;22901:96;36865:12;36838:40;;36856:7;36838:40;;36850:4;36838:40;;;;;;;;;;-1:-1:-1;36899:4:0;36892:11;;36740:217;-1:-1:-1;36941:5:0;36934:12;;37198:317;37276:4;33422:12;;;;;;;;;;;:29;;;;;;;;;;;;;37292:217;;;37366:5;37334:12;;;;;;;;;;;:29;;;;;;;;;;;:37;;;;;;37390:40;22980:10;;37334:12;;37390:40;;37366:5;37390:40;-1:-1:-1;37451:4:0;37444:11;;26150:160;26259:43;;;26274:14;4528:55:1;;26259:43:0;;;4510:74:1;4600:18;;;;4593:34;;;26259:43:0;;;;;;;;;;4483:18:1;;;;26259:43:0;;;;;;;;;;;;;;26232:71;;26252:5;;26232:19;:71::i;33900:197::-;33399:4;33422:12;;;;;;;;;;;:29;;;;;;;;;;;;;33983:108;;34033:47;;;;;4540:42:1;4528:55;;34033:47:0;;;4510:74:1;4600:18;;;4593:34;;;4483:18;;34033:47:0;4336:297:1;28906:629:0;29325:23;29351:33;:27;;;29379:4;29351:27;:33::i;:::-;29325:59;;29398:10;:17;29419:1;29398:22;;:57;;;;;29436:10;29425:30;;;;;;;;;;;;:::i;:::-;29424:31;29398:57;29394:135;;;29478:40;;;;;3125:42:1;3113:55;;29478:40:0;;;3095:74:1;3068:18;;29478:40:0;2949:226:1;18686:151:0;18761:12;18792:38;18814:6;18822:4;18828:1;18792:21;:38::i;:::-;18785:45;18686:151;-1:-1:-1;;;18686:151:0:o;19161:392::-;19260:12;19312:5;19288:21;:29;19284:108;;;19340:41;;;;;19375:4;19340:41;;;3095:74:1;3068:18;;19340:41:0;2949:226:1;19284:108:0;19402:12;19416:23;19443:6;:11;;19462:5;19469:4;19443:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19401:73;;;;19491:55;19518:6;19526:7;19535:10;19491:26;:55::i;:::-;19484:62;19161:392;-1:-1:-1;;;;;;19161:392:0:o;20606:582::-;20750:12;20779:7;20774:408;;20802:19;20810:10;20802:7;:19::i;:::-;20774:408;;;21026:17;;:22;:49;;;;-1:-1:-1;21052:18:0;;;;:23;21026:49;21022:119;;;21102:24;;;;;3125:42:1;3113:55;;21102:24:0;;;3095:74:1;3068:18;;21102:24:0;2949:226:1;21022:119:0;-1:-1:-1;21161:10:0;21154:17;;21724:516;21855:17;;:21;21851:383;;22083:10;22077:17;22139:15;22126:10;22122:2;22118:19;22111:44;21851:383;22206:17;;;;;;;;;;;;;;14:332:1;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;180:9;167:23;230:66;223:5;219:78;212:5;209:89;199:117;;312:1;309;302:12;725:196;793:20;;853:42;842:54;;832:65;;822:93;;911:1;908;901:12;822:93;725:196;;;:::o;926:260::-;994:6;1002;1055:2;1043:9;1034:7;1030:23;1026:32;1023:52;;;1071:1;1068;1061:12;1023:52;1094:29;1113:9;1094:29;:::i;:::-;1084:39;;1142:38;1176:2;1165:9;1161:18;1142:38;:::i;:::-;1132:48;;926:260;;;;;:::o;1373:180::-;1432:6;1485:2;1473:9;1464:7;1460:23;1456:32;1453:52;;;1501:1;1498;1491:12;1453:52;-1:-1:-1;1524:23:1;;1373:180;-1:-1:-1;1373:180:1:o;1558:254::-;1626:6;1634;1687:2;1675:9;1666:7;1662:23;1658:32;1655:52;;;1703:1;1700;1693:12;1655:52;1739:9;1726:23;1716:33;;1768:38;1802:2;1791:9;1787:18;1768:38;:::i;1817:186::-;1876:6;1929:2;1917:9;1908:7;1904:23;1900:32;1897:52;;;1945:1;1942;1935:12;1897:52;1968:29;1987:9;1968:29;:::i;4940:277::-;5007:6;5060:2;5048:9;5039:7;5035:23;5031:32;5028:52;;;5076:1;5073;5066:12;5028:52;5108:9;5102:16;5161:5;5154:13;5147:21;5140:5;5137:32;5127:60;;5183:1;5180;5173:12;5222:412;5351:3;5389:6;5383:13;5414:1;5424:129;5438:6;5435:1;5432:13;5424:129;;;5536:4;5520:14;;;5516:25;;5510:32;5497:11;;;5490:53;5453:12;5424:129;;;-1:-1:-1;5608:1:1;5572:16;;5597:13;;;-1:-1:-1;5572:16:1;5222:412;-1:-1:-1;5222:412:1:o","abiDefinition":[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldChainGasAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"ChainGasAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFeeRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"FeeRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesSwept","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"governor","type":"address"}],"name":"GovernorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"governor","type":"address"}],"name":"GovernorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guard","type":"address"}],"name":"GuardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guard","type":"address"}],"name":"GuardRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_RATE_MAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GOVERNOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GUARD_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAYER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_governor","type":"address"}],"name":"addGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guard","type":"address"}],"name":"addGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_relayer","type":"address"}],"name":"addRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chainGasAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"protocolFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_governor","type":"address"}],"name":"removeGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guard","type":"address"}],"name":"removeGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_relayer","type":"address"}],"name":"removeRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"setChainGasAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"setProtocolFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"sweepProtocolFees","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"chainGasAmount()":{"notice":"Chain gas amount to forward as rebate if requested"},"protocolFeeRate()":{"notice":"Protocol fee rate taken on origin amount deposited in origin chain"},"protocolFees(address)":{"notice":"Protocol fee amounts accumulated"}},"version":1},"developerDoc":{"errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}],"AddressEmptyCode(address)":[{"details":"There's no code at `target` (it is not a contract)."}],"AddressInsufficientBalance(address)":[{"details":"The ETH balance of the account is not enough to perform the operation."}],"FailedInnerCall()":[{"details":"A call to an address target failed. The target may have reverted."}],"SafeERC20FailedOperation(address)":[{"details":"An operation with an ERC-20 token failed."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"addGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"addGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"addRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"removeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"removeGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"removeRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}],\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"AddressInsufficientBalance(address)\":[{\"details\":\"The ETH balance of the account is not enough to perform the operation.\"}],\"FailedInnerCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"chainGasAmount()\":{\"notice\":\"Chain gas amount to forward as rebate if requested\"},\"protocolFeeRate()\":{\"notice\":\"Protocol fee rate taken on origin amount deposited in origin chain\"},\"protocolFees(address)\":{\"notice\":\"Protocol fee amounts accumulated\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"Admin\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0xfdd0a71cdd1fe45137a59bc8e7544699eb71ead398af2fd0f1cf448a878ccacd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://07ce767dbb21de80ca0b546310d3c374ed7ddcf5376c7085f15c7812f7678819\",\"dweb:/ipfs/QmQ3JUoivC7YRSxZnRstRKmJJ8x8cLLhEbgWsiXV5NmYrs\"]}},\"version\":1}"},"hashes":{"DEFAULT_ADMIN_ROLE()":"a217fddf","FEE_BPS()":"bf333f2c","FEE_RATE_MAX()":"0f5f6ed7","GOVERNOR_ROLE()":"ccc57490","GUARD_ROLE()":"03ed0ee5","RELAYER_ROLE()":"926d7d7f","addGovernor(address)":"3c4a25d0","addGuard(address)":"6913a63c","addRelayer(address)":"dd39f00d","chainGasAmount()":"e00a83e0","getRoleAdmin(bytes32)":"248a9ca3","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","protocolFeeRate()":"58f85880","protocolFees(address)":"dcf844a7","removeGovernor(address)":"eecdac88","removeGuard(address)":"b6235016","removeRelayer(address)":"60f0a5ac","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","setChainGasAmount(uint256)":"b250fe6b","setProtocolFeeRate(uint256)":"b13aa2d6","supportsInterface(bytes4)":"01ffc9a7","sweepProtocolFees(address,address)":"06f333f2"}},"solidity/FastBridgeMock.sol:Context":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n ) external {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.","kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"details\":\"Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"Context\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0xfdd0a71cdd1fe45137a59bc8e7544699eb71ead398af2fd0f1cf448a878ccacd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://07ce767dbb21de80ca0b546310d3c374ed7ddcf5376c7085f15c7812f7678819\",\"dweb:/ipfs/QmQ3JUoivC7YRSxZnRstRKmJJ8x8cLLhEbgWsiXV5NmYrs\"]}},\"version\":1}"},"hashes":{}},"solidity/FastBridgeMock.sol:ERC165":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n ) external {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Implementation of the {IERC165} interface. Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check for the additional interface id that will be supported. For example: ```solidity function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); } ```","kind":"dev","methods":{"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Implementation of the {IERC165} interface. Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check for the additional interface id that will be supported. For example: ```solidity function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); } ```\",\"kind\":\"dev\",\"methods\":{\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"ERC165\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0xfdd0a71cdd1fe45137a59bc8e7544699eb71ead398af2fd0f1cf448a878ccacd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://07ce767dbb21de80ca0b546310d3c374ed7ddcf5376c7085f15c7812f7678819\",\"dweb:/ipfs/QmQ3JUoivC7YRSxZnRstRKmJJ8x8cLLhEbgWsiXV5NmYrs\"]}},\"version\":1}"},"hashes":{"supportsInterface(bytes4)":"01ffc9a7"}},"solidity/FastBridgeMock.sol:FastBridge":{"code":"0x60a06040523480156200001157600080fd5b5060405162003105380380620031058339810160408190526200003491620000fe565b80620000426000826200004f565b5050436080525062000130565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16620000f4576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620000ab3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001620000f8565b5060005b92915050565b6000602082840312156200011157600080fd5b81516001600160a01b03811681146200012957600080fd5b9392505050565b608051612fb96200014c600039600061067f0152612fb96000f3fe6080604052600436106102bb5760003560e01c806391d148541161016e578063b250fe6b116100cb578063d547741f1161007f578063dd39f00d11610064578063dd39f00d14610832578063e00a83e014610852578063eecdac881461086857600080fd5b8063d547741f146107e5578063dcf844a71461080557600080fd5b8063bf333f2c116100b0578063bf333f2c14610784578063ccc574901461079b578063d3cbc760146107cf57600080fd5b8063b250fe6b14610744578063b62350161461076457600080fd5b8063aa9641ab11610122578063add98c7011610107578063add98c70146106ee578063affed0e01461070e578063b13aa2d61461072457600080fd5b8063aa9641ab146106a1578063ac11fb1a146106c157600080fd5b8063a217fddf11610153578063a217fddf14610658578063a3ec191a1461066d578063a5bbe22b146104e557600080fd5b806391d14854146105e0578063926d7d7f1461062457600080fd5b8063458516941161021c578063820688d5116101d0578063886d36ff116101b5578063886d36ff1461052b5780638f0d6f171461054b57806391ad50391461055e57600080fd5b8063820688d5146104e55780638379a24f146104fb57600080fd5b80635eb7d946116102015780635eb7d9461461048557806360f0a5ac146104a55780636913a63c146104c557600080fd5b8063458516941461045c57806358f858801461046f57600080fd5b8063248a9ca31161027357806336568abe1161025857806336568abe146103fc5780633c4a25d01461041c57806341fcb6121461043c57600080fd5b8063248a9ca3146103ac5780632f2ff15d146103dc57600080fd5b8063051287bc116102a4578063051287bc1461033757806306f333f2146103745780630f5f6ed71461039657600080fd5b806301ffc9a7146102c057806303ed0ee5146102f5575b600080fd5b3480156102cc57600080fd5b506102e06102db366004612796565b610888565b60405190151581526020015b60405180910390f35b34801561030157600080fd5b506103297f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b6040519081526020016102ec565b34801561034357600080fd5b506103676103523660046127d8565b60046020526000908152604090205460ff1681565b6040516102ec9190612820565b34801561038057600080fd5b5061039461038f366004612886565b610921565b005b3480156103a257600080fd5b5061032961271081565b3480156103b857600080fd5b506103296103c73660046127d8565b60009081526020819052604090206001015490565b3480156103e857600080fd5b506103946103f73660046128bf565b610a59565b34801561040857600080fd5b506103946104173660046128bf565b610a84565b34801561042857600080fd5b506103946104373660046128e4565b610ad5565b34801561044857600080fd5b50610394610457366004612a29565b610b7b565b61039461046a366004612aa6565b610e23565b34801561047b57600080fd5b5061032960015481565b34801561049157600080fd5b506103946104a0366004612b49565b611131565b3480156104b157600080fd5b506103946104c03660046128e4565b611294565b3480156104d157600080fd5b506103946104e03660046128e4565b611333565b3480156104f157600080fd5b5061032961070881565b34801561050757600080fd5b506102e06105163660046127d8565b60066020526000908152604090205460ff1681565b34801561053757600080fd5b50610394610546366004612b86565b6113d2565b610394610559366004612b49565b6115ce565b34801561056a57600080fd5b506105b46105793660046127d8565b6005602052600090815260409020546bffffffffffffffffffffffff8116906c0100000000000000000000000090046001600160a01b031682565b604080516bffffffffffffffffffffffff90931683526001600160a01b039091166020830152016102ec565b3480156105ec57600080fd5b506102e06105fb3660046128bf565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561063057600080fd5b506103297fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b34801561066457600080fd5b50610329600081565b34801561067957600080fd5b506103297f000000000000000000000000000000000000000000000000000000000000000081565b3480156106ad57600080fd5b506102e06106bc3660046128bf565b611883565b3480156106cd57600080fd5b506106e16106dc366004612b49565b611988565b6040516102ec9190612bcb565b3480156106fa57600080fd5b506103946107093660046127d8565b6119fb565b34801561071a57600080fd5b5061032960075481565b34801561073057600080fd5b5061039461073f3660046127d8565b611bd3565b34801561075057600080fd5b5061039461075f3660046127d8565b611d1d565b34801561077057600080fd5b5061039461077f3660046128e4565b611df3565b34801561079057600080fd5b50610329620f424081565b3480156107a757600080fd5b506103297f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b3480156107db57600080fd5b50610329610e1081565b3480156107f157600080fd5b506103946108003660046128bf565b611e92565b34801561081157600080fd5b506103296108203660046128e4565b60026020526000908152604090205481565b34801561083e57600080fd5b5061039461084d3660046128e4565b611eb7565b34801561085e57600080fd5b5061032960035481565b34801561087457600080fd5b506103946108833660046128e4565b611f56565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061091b57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff166109be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064015b60405180910390fd5b6001600160a01b038216600090815260026020526040812054908190036109e457505050565b6001600160a01b038316600081815260026020526040812055610a08908383611ff5565b604080516001600160a01b038086168252841660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b5050565b600082815260208190526040902060010154610a7481612118565b610a7e8383612125565b50505050565b6001600160a01b0381163314610ac6576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ad082826121cf565b505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610b1057600080fd5b610b3a7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5582612125565b506040516001600160a01b03821681527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5906020015b60405180910390a150565b3360009081527ffaf93c3d007e112089dc8351e013e6685ef67703975d0224b26fc45941d4f1f5602052604090205460ff16610c13576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616c6c6572206973206e6f7420612072656c6179657200000000000000000060448201526064016109b5565b815160208301206000610c2584611988565b9050600260008381526004602081905260409091205460ff1690811115610c4e57610c4e6127f1565b14610c85576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040918290208251808401909352546bffffffffffffffffffffffff811683526c0100000000000000000000000090046001600160a01b03169082018190523314610d08576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611610d55576040517f1992d0bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600460205260409020805460ff1916600317905561010082015115610db15761010082015160808301516001600160a01b031660009081526002602052604081208054909190610dab908490612ce0565b90915550505b608082015160c0830151610dcf6001600160a01b0383168783611ff5565b604080516001600160a01b03848116825260208201849052881691339188917f582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac67891015b60405180910390a450505050505050565b46816000015163ffffffff1603610e66576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a08101511580610e79575060c0810151155b15610eb0576040517fe38820c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608101516001600160a01b03161580610ed5575060808101516001600160a01b0316155b15610f0c576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f1861070842612ce0565b8161010001511015610f56576040517f04b7fcc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610f6b3083606001518460a00151612252565b90506000806001541115610f9857620f424060015483610f8b9190612cf3565b610f959190612d0a565b90505b610fa28183612d45565b915060006040518061018001604052804663ffffffff168152602001856000015163ffffffff16815260200185602001516001600160a01b0316815260200185604001516001600160a01b0316815260200185606001516001600160a01b0316815260200185608001516001600160a01b031681526020018481526020018560c0015181526020018381526020018560e001511515815260200185610100015181526020016007600081548092919061105a90612d58565b9091555090526040516110709190602001612bcb565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152828252805160208083019190912060008181526004835293909320805460ff191660011790558701518751606089015160808a015160c08b015160e08c015195985095966001600160a01b039094169587957f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a95611122958b959094909390928e92612db4565b60405180910390a35050505050565b80516020820120600061114383611988565b9050610e108161014001516111589190612ce0565b4211611190576040517fe15ff9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008381526004602081905260409091205460ff16908111156111b7576111b76127f1565b146111ee576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600460208190526040909120805460ff191660018302179055506040810151608082015161010083015160c084015160009161122e91612ce0565b90506112446001600160a01b0383168483611ff5565b604080516001600160a01b0384811682526020820184905285169187917fb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958910160405180910390a3505050505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166112cf57600080fd5b6112f97fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4826121cf565b506040516001600160a01b03821681527f10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b90602001610b70565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661136e57600080fd5b6113987f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d82612125565b506040516001600160a01b03821681527f93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f5990602001610b70565b3360009081527ffaf93c3d007e112089dc8351e013e6685ef67703975d0224b26fc45941d4f1f5602052604090205460ff1661146a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616c6c6572206973206e6f7420612072656c6179657200000000000000000060448201526064016109b5565b81516020830120600061147c84611988565b9050610e108161014001516114919190612ce0565b4211156114ca576040517f559895a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008381526004602081905260409091205460ff16908111156114f1576114f16127f1565b14611528576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526004602090815260408083208054600260ff19909116179055805180820182526bffffffffffffffffffffffff4281168252338285018181528887526005865295849020925195516001600160a01b03166c0100000000000000000000000002959091169490941790555185815284917f4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4910160405180910390a350505050565b3360009081527ffaf93c3d007e112089dc8351e013e6685ef67703975d0224b26fc45941d4f1f5602052604090205460ff16611666576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616c6c6572206973206e6f7420612072656c6179657200000000000000000060448201526064016109b5565b80516020820120600061167883611988565b90504663ffffffff16816020015163ffffffff16146116c3576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806101400151421115611702576040517f559895a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205460ff161561174b576040517fbef7bb7d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660205260409020805460ff19166001179055606081015160a082015160e08301516003546101208501516117945750600061178e848484612252565b50611805565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b038416016117d85761178e84846117d38486612ce0565b612252565b6117e3848484612252565b506118038473eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee83612252565b505b845160808087015160a08089015160c0808b015160e08c01516040805163ffffffff90991689526001600160a01b0396871660208a0152938616938801939093526060870152938501528301849052861691339189917ff8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c9101610e12565b6000600260008481526004602081905260409091205460ff16908111156118ac576118ac6127f1565b146118e3576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600560209081526040918290208251808401909352546bffffffffffffffffffffffff811683526001600160a01b036c010000000000000000000000009091048116918301829052841614611969576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611949350505050565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201528251909161091b9184018101908401612e65565b3360009081527f92bf2f06c618f6add65571bf52eb90d22c9b52fd65028daa87260b82998b30bd602052604090205460ff16611a93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f43616c6c6572206973206e6f742061206775617264000000000000000000000060448201526064016109b5565b600260008281526004602081905260409091205460ff1690811115611aba57611aba6127f1565b14611af1576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600560209081526040918290208251808401909352546bffffffffffffffffffffffff8082168085526c010000000000000000000000009092046001600160a01b03169390920192909252610708914203161115611b80576040517f3e908aac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460209081526040808320805460ff19166001179055600590915280822082905551339183917f0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad49190a350565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16611c6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064016109b5565b612710811115611cd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064016109b5565b600180549082905560408051828152602081018490527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a15050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16611db5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064016109b5565b600380549082905560408051828152602081018490527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa9101611d11565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611e2e57600080fd5b611e587f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d826121cf565b506040516001600160a01b03821681527f59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d04890602001610b70565b600082815260208190526040902060010154611ead81612118565b610a7e83836121cf565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611ef257600080fd5b611f1c7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc482612125565b506040516001600160a01b03821681527f03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c590602001610b70565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611f9157600080fd5b611fbb7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55826121cf565b506040516001600160a01b03821681527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b90602001610b70565b306001600160a01b0383160361200a57505050565b8060000361201757505050565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03841601612104576000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612094576040519150601f19603f3d011682016040523d82523d6000602084013e612099565b606091505b5050905080610a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c65640000000000000000000000000060448201526064016109b5565b610ad06001600160a01b0384168383612422565b6121228133612496565b50565b6000828152602081815260408083206001600160a01b038516845290915281205460ff166121c7576000838152602081815260408083206001600160a01b03861684529091529020805460ff1916600117905561217f3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161091b565b50600061091b565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16156121c7576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161091b565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146123bb5761228a836001600160a01b0316612502565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528416906370a0823190602401602060405180830381865afa1580156122e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061230d9190612f31565b90506123246001600160a01b0384163386856125a8565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528291908516906370a0823190602401602060405180830381865afa158015612386573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123aa9190612f31565b6123b49190612d45565b905061241b565b3482146123f4576040517f81de0bf300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0384163014612418576124186001600160a01b0384168584611ff5565b50345b9392505050565b6040516001600160a01b03838116602483015260448201839052610ad091859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506125e1565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610a55576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602481018390526044016109b5565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03821601612564576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03163b600003612122576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038481166024830152838116604483015260648201839052610a7e9186918216906323b872dd9060840161244f565b60006125f66001600160a01b0384168361265d565b9050805160001415801561261b5750808060200190518101906126199190612f4a565b155b15610ad0576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024016109b5565b606061241b8383600084600080856001600160a01b031684866040516126839190612f67565b60006040518083038185875af1925050503d80600081146126c0576040519150601f19603f3d011682016040523d82523d6000602084013e6126c5565b606091505b50915091506126d58683836126df565b9695505050505050565b6060826126f4576126ef82612754565b61241b565b815115801561270b57506001600160a01b0384163b155b1561274d576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016109b5565b508061241b565b8051156127645780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602082840312156127a857600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461241b57600080fd5b6000602082840312156127ea57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016005831061285b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6001600160a01b038116811461212257600080fd5b803561288181612861565b919050565b6000806040838503121561289957600080fd5b82356128a481612861565b915060208301356128b481612861565b809150509250929050565b600080604083850312156128d257600080fd5b8235915060208301356128b481612861565b6000602082840312156128f657600080fd5b813561241b81612861565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171561295457612954612901565b60405290565b604051610180810167ffffffffffffffff8111828210171561295457612954612901565b600082601f83011261298f57600080fd5b813567ffffffffffffffff808211156129aa576129aa612901565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156129f0576129f0612901565b81604052838152866020858801011115612a0957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215612a3c57600080fd5b823567ffffffffffffffff811115612a5357600080fd5b612a5f8582860161297e565b92505060208301356128b481612861565b63ffffffff8116811461212257600080fd5b803561288181612a70565b801515811461212257600080fd5b803561288181612a8d565b60006101208284031215612ab957600080fd5b612ac1612930565b612aca83612a82565b8152612ad860208401612876565b6020820152612ae960408401612876565b6040820152612afa60608401612876565b6060820152612b0b60808401612876565b608082015260a083013560a082015260c083013560c0820152612b3060e08401612a9b565b60e0820152610100928301359281019290925250919050565b600060208284031215612b5b57600080fd5b813567ffffffffffffffff811115612b7257600080fd5b612b7e8482850161297e565b949350505050565b60008060408385031215612b9957600080fd5b823567ffffffffffffffff811115612bb057600080fd5b612bbc8582860161297e565b95602094909401359450505050565b815163ffffffff16815261018081016020830151612bf1602084018263ffffffff169052565b506040830151612c0c60408401826001600160a01b03169052565b506060830151612c2760608401826001600160a01b03169052565b506080830151612c4260808401826001600160a01b03169052565b5060a0830151612c5d60a08401826001600160a01b03169052565b5060c083015160c083015260e083015160e083015261010080840151818401525061012080840151612c928285018215159052565b5050610140838101519083015261016092830151929091019190915290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561091b5761091b612cb1565b808202811582820484141761091b5761091b612cb1565b600082612d40577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561091b5761091b612cb1565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612d8957612d89612cb1565b5060010190565b60005b83811015612dab578181015183820152602001612d93565b50506000910152565b60e08152600088518060e0840152610100612dd58282860160208e01612d90565b63ffffffff9990991660208401526001600160a01b039788166040840152959096166060820152608081019390935260a0830191909152151560c0820152601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190910192915050565b805161288181612a70565b805161288181612861565b805161288181612a8d565b60006101808284031215612e7857600080fd5b612e8061295a565b612e8983612e44565b8152612e9760208401612e44565b6020820152612ea860408401612e4f565b6040820152612eb960608401612e4f565b6060820152612eca60808401612e4f565b6080820152612edb60a08401612e4f565b60a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120612f0e818501612e5a565b908201526101408381015190820152610160928301519281019290925250919050565b600060208284031215612f4357600080fd5b5051919050565b600060208284031215612f5c57600080fd5b815161241b81612a8d565b60008251612f79818460208701612d90565b919091019291505056fea26469706673582212201d3a10322561f18b095a55071d44fc12bf9e48f853c53f8cfe4c3915d4f3009764736f6c63430008140033","runtime-code":"0x6080604052600436106102bb5760003560e01c806391d148541161016e578063b250fe6b116100cb578063d547741f1161007f578063dd39f00d11610064578063dd39f00d14610832578063e00a83e014610852578063eecdac881461086857600080fd5b8063d547741f146107e5578063dcf844a71461080557600080fd5b8063bf333f2c116100b0578063bf333f2c14610784578063ccc574901461079b578063d3cbc760146107cf57600080fd5b8063b250fe6b14610744578063b62350161461076457600080fd5b8063aa9641ab11610122578063add98c7011610107578063add98c70146106ee578063affed0e01461070e578063b13aa2d61461072457600080fd5b8063aa9641ab146106a1578063ac11fb1a146106c157600080fd5b8063a217fddf11610153578063a217fddf14610658578063a3ec191a1461066d578063a5bbe22b146104e557600080fd5b806391d14854146105e0578063926d7d7f1461062457600080fd5b8063458516941161021c578063820688d5116101d0578063886d36ff116101b5578063886d36ff1461052b5780638f0d6f171461054b57806391ad50391461055e57600080fd5b8063820688d5146104e55780638379a24f146104fb57600080fd5b80635eb7d946116102015780635eb7d9461461048557806360f0a5ac146104a55780636913a63c146104c557600080fd5b8063458516941461045c57806358f858801461046f57600080fd5b8063248a9ca31161027357806336568abe1161025857806336568abe146103fc5780633c4a25d01461041c57806341fcb6121461043c57600080fd5b8063248a9ca3146103ac5780632f2ff15d146103dc57600080fd5b8063051287bc116102a4578063051287bc1461033757806306f333f2146103745780630f5f6ed71461039657600080fd5b806301ffc9a7146102c057806303ed0ee5146102f5575b600080fd5b3480156102cc57600080fd5b506102e06102db366004612796565b610888565b60405190151581526020015b60405180910390f35b34801561030157600080fd5b506103297f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b6040519081526020016102ec565b34801561034357600080fd5b506103676103523660046127d8565b60046020526000908152604090205460ff1681565b6040516102ec9190612820565b34801561038057600080fd5b5061039461038f366004612886565b610921565b005b3480156103a257600080fd5b5061032961271081565b3480156103b857600080fd5b506103296103c73660046127d8565b60009081526020819052604090206001015490565b3480156103e857600080fd5b506103946103f73660046128bf565b610a59565b34801561040857600080fd5b506103946104173660046128bf565b610a84565b34801561042857600080fd5b506103946104373660046128e4565b610ad5565b34801561044857600080fd5b50610394610457366004612a29565b610b7b565b61039461046a366004612aa6565b610e23565b34801561047b57600080fd5b5061032960015481565b34801561049157600080fd5b506103946104a0366004612b49565b611131565b3480156104b157600080fd5b506103946104c03660046128e4565b611294565b3480156104d157600080fd5b506103946104e03660046128e4565b611333565b3480156104f157600080fd5b5061032961070881565b34801561050757600080fd5b506102e06105163660046127d8565b60066020526000908152604090205460ff1681565b34801561053757600080fd5b50610394610546366004612b86565b6113d2565b610394610559366004612b49565b6115ce565b34801561056a57600080fd5b506105b46105793660046127d8565b6005602052600090815260409020546bffffffffffffffffffffffff8116906c0100000000000000000000000090046001600160a01b031682565b604080516bffffffffffffffffffffffff90931683526001600160a01b039091166020830152016102ec565b3480156105ec57600080fd5b506102e06105fb3660046128bf565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561063057600080fd5b506103297fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b34801561066457600080fd5b50610329600081565b34801561067957600080fd5b506103297f000000000000000000000000000000000000000000000000000000000000000081565b3480156106ad57600080fd5b506102e06106bc3660046128bf565b611883565b3480156106cd57600080fd5b506106e16106dc366004612b49565b611988565b6040516102ec9190612bcb565b3480156106fa57600080fd5b506103946107093660046127d8565b6119fb565b34801561071a57600080fd5b5061032960075481565b34801561073057600080fd5b5061039461073f3660046127d8565b611bd3565b34801561075057600080fd5b5061039461075f3660046127d8565b611d1d565b34801561077057600080fd5b5061039461077f3660046128e4565b611df3565b34801561079057600080fd5b50610329620f424081565b3480156107a757600080fd5b506103297f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b3480156107db57600080fd5b50610329610e1081565b3480156107f157600080fd5b506103946108003660046128bf565b611e92565b34801561081157600080fd5b506103296108203660046128e4565b60026020526000908152604090205481565b34801561083e57600080fd5b5061039461084d3660046128e4565b611eb7565b34801561085e57600080fd5b5061032960035481565b34801561087457600080fd5b506103946108833660046128e4565b611f56565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061091b57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff166109be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064015b60405180910390fd5b6001600160a01b038216600090815260026020526040812054908190036109e457505050565b6001600160a01b038316600081815260026020526040812055610a08908383611ff5565b604080516001600160a01b038086168252841660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b5050565b600082815260208190526040902060010154610a7481612118565b610a7e8383612125565b50505050565b6001600160a01b0381163314610ac6576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ad082826121cf565b505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610b1057600080fd5b610b3a7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5582612125565b506040516001600160a01b03821681527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5906020015b60405180910390a150565b3360009081527ffaf93c3d007e112089dc8351e013e6685ef67703975d0224b26fc45941d4f1f5602052604090205460ff16610c13576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616c6c6572206973206e6f7420612072656c6179657200000000000000000060448201526064016109b5565b815160208301206000610c2584611988565b9050600260008381526004602081905260409091205460ff1690811115610c4e57610c4e6127f1565b14610c85576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040918290208251808401909352546bffffffffffffffffffffffff811683526c0100000000000000000000000090046001600160a01b03169082018190523314610d08576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611610d55576040517f1992d0bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600460205260409020805460ff1916600317905561010082015115610db15761010082015160808301516001600160a01b031660009081526002602052604081208054909190610dab908490612ce0565b90915550505b608082015160c0830151610dcf6001600160a01b0383168783611ff5565b604080516001600160a01b03848116825260208201849052881691339188917f582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac67891015b60405180910390a450505050505050565b46816000015163ffffffff1603610e66576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a08101511580610e79575060c0810151155b15610eb0576040517fe38820c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608101516001600160a01b03161580610ed5575060808101516001600160a01b0316155b15610f0c576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f1861070842612ce0565b8161010001511015610f56576040517f04b7fcc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610f6b3083606001518460a00151612252565b90506000806001541115610f9857620f424060015483610f8b9190612cf3565b610f959190612d0a565b90505b610fa28183612d45565b915060006040518061018001604052804663ffffffff168152602001856000015163ffffffff16815260200185602001516001600160a01b0316815260200185604001516001600160a01b0316815260200185606001516001600160a01b0316815260200185608001516001600160a01b031681526020018481526020018560c0015181526020018381526020018560e001511515815260200185610100015181526020016007600081548092919061105a90612d58565b9091555090526040516110709190602001612bcb565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152828252805160208083019190912060008181526004835293909320805460ff191660011790558701518751606089015160808a015160c08b015160e08c015195985095966001600160a01b039094169587957f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a95611122958b959094909390928e92612db4565b60405180910390a35050505050565b80516020820120600061114383611988565b9050610e108161014001516111589190612ce0565b4211611190576040517fe15ff9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008381526004602081905260409091205460ff16908111156111b7576111b76127f1565b146111ee576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600460208190526040909120805460ff191660018302179055506040810151608082015161010083015160c084015160009161122e91612ce0565b90506112446001600160a01b0383168483611ff5565b604080516001600160a01b0384811682526020820184905285169187917fb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958910160405180910390a3505050505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166112cf57600080fd5b6112f97fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4826121cf565b506040516001600160a01b03821681527f10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b90602001610b70565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661136e57600080fd5b6113987f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d82612125565b506040516001600160a01b03821681527f93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f5990602001610b70565b3360009081527ffaf93c3d007e112089dc8351e013e6685ef67703975d0224b26fc45941d4f1f5602052604090205460ff1661146a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616c6c6572206973206e6f7420612072656c6179657200000000000000000060448201526064016109b5565b81516020830120600061147c84611988565b9050610e108161014001516114919190612ce0565b4211156114ca576040517f559895a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008381526004602081905260409091205460ff16908111156114f1576114f16127f1565b14611528576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526004602090815260408083208054600260ff19909116179055805180820182526bffffffffffffffffffffffff4281168252338285018181528887526005865295849020925195516001600160a01b03166c0100000000000000000000000002959091169490941790555185815284917f4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4910160405180910390a350505050565b3360009081527ffaf93c3d007e112089dc8351e013e6685ef67703975d0224b26fc45941d4f1f5602052604090205460ff16611666576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616c6c6572206973206e6f7420612072656c6179657200000000000000000060448201526064016109b5565b80516020820120600061167883611988565b90504663ffffffff16816020015163ffffffff16146116c3576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806101400151421115611702576040517f559895a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205460ff161561174b576040517fbef7bb7d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660205260409020805460ff19166001179055606081015160a082015160e08301516003546101208501516117945750600061178e848484612252565b50611805565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b038416016117d85761178e84846117d38486612ce0565b612252565b6117e3848484612252565b506118038473eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee83612252565b505b845160808087015160a08089015160c0808b015160e08c01516040805163ffffffff90991689526001600160a01b0396871660208a0152938616938801939093526060870152938501528301849052861691339189917ff8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c9101610e12565b6000600260008481526004602081905260409091205460ff16908111156118ac576118ac6127f1565b146118e3576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600560209081526040918290208251808401909352546bffffffffffffffffffffffff811683526001600160a01b036c010000000000000000000000009091048116918301829052841614611969576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611949350505050565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201528251909161091b9184018101908401612e65565b3360009081527f92bf2f06c618f6add65571bf52eb90d22c9b52fd65028daa87260b82998b30bd602052604090205460ff16611a93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f43616c6c6572206973206e6f742061206775617264000000000000000000000060448201526064016109b5565b600260008281526004602081905260409091205460ff1690811115611aba57611aba6127f1565b14611af1576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600560209081526040918290208251808401909352546bffffffffffffffffffffffff8082168085526c010000000000000000000000009092046001600160a01b03169390920192909252610708914203161115611b80576040517f3e908aac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460209081526040808320805460ff19166001179055600590915280822082905551339183917f0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad49190a350565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16611c6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064016109b5565b612710811115611cd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064016109b5565b600180549082905560408051828152602081018490527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a15050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16611db5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064016109b5565b600380549082905560408051828152602081018490527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa9101611d11565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611e2e57600080fd5b611e587f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d826121cf565b506040516001600160a01b03821681527f59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d04890602001610b70565b600082815260208190526040902060010154611ead81612118565b610a7e83836121cf565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611ef257600080fd5b611f1c7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc482612125565b506040516001600160a01b03821681527f03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c590602001610b70565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16611f9157600080fd5b611fbb7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55826121cf565b506040516001600160a01b03821681527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b90602001610b70565b306001600160a01b0383160361200a57505050565b8060000361201757505050565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03841601612104576000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612094576040519150601f19603f3d011682016040523d82523d6000602084013e612099565b606091505b5050905080610a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c65640000000000000000000000000060448201526064016109b5565b610ad06001600160a01b0384168383612422565b6121228133612496565b50565b6000828152602081815260408083206001600160a01b038516845290915281205460ff166121c7576000838152602081815260408083206001600160a01b03861684529091529020805460ff1916600117905561217f3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161091b565b50600061091b565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16156121c7576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161091b565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146123bb5761228a836001600160a01b0316612502565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528416906370a0823190602401602060405180830381865afa1580156122e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061230d9190612f31565b90506123246001600160a01b0384163386856125a8565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528291908516906370a0823190602401602060405180830381865afa158015612386573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123aa9190612f31565b6123b49190612d45565b905061241b565b3482146123f4576040517f81de0bf300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0384163014612418576124186001600160a01b0384168584611ff5565b50345b9392505050565b6040516001600160a01b03838116602483015260448201839052610ad091859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506125e1565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610a55576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602481018390526044016109b5565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03821601612564576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03163b600003612122576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038481166024830152838116604483015260648201839052610a7e9186918216906323b872dd9060840161244f565b60006125f66001600160a01b0384168361265d565b9050805160001415801561261b5750808060200190518101906126199190612f4a565b155b15610ad0576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024016109b5565b606061241b8383600084600080856001600160a01b031684866040516126839190612f67565b60006040518083038185875af1925050503d80600081146126c0576040519150601f19603f3d011682016040523d82523d6000602084013e6126c5565b606091505b50915091506126d58683836126df565b9695505050505050565b6060826126f4576126ef82612754565b61241b565b815115801561270b57506001600160a01b0384163b155b1561274d576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016109b5565b508061241b565b8051156127645780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602082840312156127a857600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461241b57600080fd5b6000602082840312156127ea57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016005831061285b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6001600160a01b038116811461212257600080fd5b803561288181612861565b919050565b6000806040838503121561289957600080fd5b82356128a481612861565b915060208301356128b481612861565b809150509250929050565b600080604083850312156128d257600080fd5b8235915060208301356128b481612861565b6000602082840312156128f657600080fd5b813561241b81612861565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171561295457612954612901565b60405290565b604051610180810167ffffffffffffffff8111828210171561295457612954612901565b600082601f83011261298f57600080fd5b813567ffffffffffffffff808211156129aa576129aa612901565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156129f0576129f0612901565b81604052838152866020858801011115612a0957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215612a3c57600080fd5b823567ffffffffffffffff811115612a5357600080fd5b612a5f8582860161297e565b92505060208301356128b481612861565b63ffffffff8116811461212257600080fd5b803561288181612a70565b801515811461212257600080fd5b803561288181612a8d565b60006101208284031215612ab957600080fd5b612ac1612930565b612aca83612a82565b8152612ad860208401612876565b6020820152612ae960408401612876565b6040820152612afa60608401612876565b6060820152612b0b60808401612876565b608082015260a083013560a082015260c083013560c0820152612b3060e08401612a9b565b60e0820152610100928301359281019290925250919050565b600060208284031215612b5b57600080fd5b813567ffffffffffffffff811115612b7257600080fd5b612b7e8482850161297e565b949350505050565b60008060408385031215612b9957600080fd5b823567ffffffffffffffff811115612bb057600080fd5b612bbc8582860161297e565b95602094909401359450505050565b815163ffffffff16815261018081016020830151612bf1602084018263ffffffff169052565b506040830151612c0c60408401826001600160a01b03169052565b506060830151612c2760608401826001600160a01b03169052565b506080830151612c4260808401826001600160a01b03169052565b5060a0830151612c5d60a08401826001600160a01b03169052565b5060c083015160c083015260e083015160e083015261010080840151818401525061012080840151612c928285018215159052565b5050610140838101519083015261016092830151929091019190915290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561091b5761091b612cb1565b808202811582820484141761091b5761091b612cb1565b600082612d40577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561091b5761091b612cb1565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612d8957612d89612cb1565b5060010190565b60005b83811015612dab578181015183820152602001612d93565b50506000910152565b60e08152600088518060e0840152610100612dd58282860160208e01612d90565b63ffffffff9990991660208401526001600160a01b039788166040840152959096166060820152608081019390935260a0830191909152151560c0820152601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190910192915050565b805161288181612a70565b805161288181612861565b805161288181612a8d565b60006101808284031215612e7857600080fd5b612e8061295a565b612e8983612e44565b8152612e9760208401612e44565b6020820152612ea860408401612e4f565b6040820152612eb960608401612e4f565b6060820152612eca60808401612e4f565b6080820152612edb60a08401612e4f565b60a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120612f0e818501612e5a565b908201526101408381015190820152610160928301519281019290925250919050565b600060208284031215612f4357600080fd5b5051919050565b600060208284031215612f5c57600080fd5b815161241b81612a8d565b60008251612f79818460208701612d90565b919091019291505056fea26469706673582212201d3a10322561f18b095a55071d44fc12bf9e48f853c53f8cfe4c3915d4f3009764736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n ) external {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"43468:11252:0:-:0;;;44636:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;44670:6;41292:38;32700:4;44670:6;41292:10;:38::i;:::-;-1:-1:-1;;44702:12:0::1;44688:26;::::0;-1:-1:-1;43468:11252:0;;36647:316;36724:4;33422:12;;;;;;;;;;;-1:-1:-1;;;;;33422:29:0;;;;;;;;;;;;36740:217;;36783:6;:12;;;;;;;;;;;-1:-1:-1;;;;;36783:29:0;;;;;;;;;:36;;-1:-1:-1;;36783:36:0;36815:4;36783:36;;;36865:12;22980:10;;22901:96;36865:12;-1:-1:-1;;;;;36838:40:0;36856:7;-1:-1:-1;;;;;36838:40:0;36850:4;36838:40;;;;;;;;;;-1:-1:-1;36899:4:0;36892:11;;36740:217;-1:-1:-1;36941:5:0;36740:217;36647:316;;;;:::o;14:290:1:-;84:6;137:2;125:9;116:7;112:23;108:32;105:52;;;153:1;150;143:12;105:52;179:16;;-1:-1:-1;;;;;224:31:1;;214:42;;204:70;;270:1;267;260:12;204:70;293:5;14:290;-1:-1:-1;;;14:290:1:o;:::-;43468:11252:0;;;;;;;;;;;;","srcMapRuntime":"43468:11252:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33033:202;;;;;;;;;;-1:-1:-1;33033:202:0;;;;;:::i;:::-;;:::i;:::-;;;612:14:1;;605:22;587:41;;575:2;560:18;33033:202:0;;;;;;;;40292:60;;;;;;;;;;;;40329:23;40292:60;;;;;785:25:1;;;773:2;758:18;40292:60:0;639:177:1;44188:54:0;;;;;;;;;;-1:-1:-1;44188:54:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;42828:348::-;;;;;;;;;;-1:-1:-1;42828:348:0;;;;;:::i;:::-;;:::i;:::-;;40474:45;;;;;;;;;;;;40513:6;40474:45;;34278:120;;;;;;;;;;-1:-1:-1;34278:120:0;;;;;:::i;:::-;34343:7;34369:12;;;;;;;;;;:22;;;;34278:120;34694:136;;;;;;;;;;-1:-1:-1;34694:136:0;;;;;:::i;:::-;;:::i;35796:245::-;;;;;;;;;;-1:-1:-1;35796:245:0;;;;;:::i;:::-;;:::i;42127:199::-;;;;;;;;;;-1:-1:-1;42127:199:0;;;;;:::i;:::-;;:::i;52078:1135::-;;;;;;;;;;-1:-1:-1;52078:1135:0;;;;;:::i;:::-;;:::i;46321:2114::-;;;;;;:::i;:::-;;:::i;40636:30::-;;;;;;;;;;;;;;;;53803:915;;;;;;;;;;-1:-1:-1;53803:915:0;;;;;:::i;:::-;;:::i;41542:199::-;;;;;;;;;;-1:-1:-1;41542:199:0;;;;;:::i;:::-;;:::i;41747:181::-;;;;;;;;;;-1:-1:-1;41747:181:0;;;;;:::i;:::-;;:::i;43918:56::-;;;;;;;;;;;;43964:10;43918:56;;44433:44;;;;;;;;;;-1:-1:-1;44433:44:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;50218:793;;;;;;;;;;-1:-1:-1;50218:793:0;;;;;:::i;:::-;;:::i;48473:1707::-;;;;;;:::i;:::-;;:::i;44307:51::-;;;;;;;;;;-1:-1:-1;44307:51:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;44307:51:0;;;;;;;7428:26:1;7416:39;;;7398:58;;-1:-1:-1;;;;;7492:55:1;;;7487:2;7472:18;;7465:83;7371:18;44307:51:0;7226:328:1;33322:136:0;;;;;;;;;;-1:-1:-1;33322:136:0;;;;;:::i;:::-;33399:4;33422:12;;;;;;;;;;;-1:-1:-1;;;;;33422:29:0;;;;;;;;;;;;;;;33322:136;40222:64;;;;;;;;;;;;40261:25;40222:64;;32655:49;;;;;;;;;;-1:-1:-1;32655:49:0;32700:4;32655:49;;44593:36;;;;;;;;;;;;;;;51667:373;;;;;;;;;;-1:-1:-1;51667:373:0;;;;;:::i;:::-;;:::i;46120:163::-;;;;;;;;;;-1:-1:-1;46120:163:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;53251:514::-;;;;;;;;;;-1:-1:-1;53251:514:0;;;;;:::i;:::-;;:::i;44516:20::-;;;;;;;;;;;;;;;;42543:279;;;;;;;;;;-1:-1:-1;42543:279:0;;;;;:::i;:::-;;:::i;43182:253::-;;;;;;;;;;-1:-1:-1;43182:253:0;;;;;:::i;:::-;;:::i;41934:187::-;;;;;;;;;;-1:-1:-1;41934:187:0;;;;;:::i;:::-;;:::i;40431:37::-;;;;;;;;;;;;40465:3;40431:37;;40358:66;;;;;;;;;;;;40398:26;40358:66;;43782:49;;;;;;;;;;;;43821:10;43782:49;;35110:138;;;;;;;;;;-1:-1:-1;35110:138:0;;;;;:::i;:::-;;:::i;40722:47::-;;;;;;;;;;-1:-1:-1;40722:47:0;;;;;:::i;:::-;;;;;;;;;;;;;;41343:193;;;;;;;;;;-1:-1:-1;41343:193:0;;;;;:::i;:::-;;:::i;40843:29::-;;;;;;;;;;;;;;;;42332:205;;;;;;;;;;-1:-1:-1;42332:205:0;;;;;:::i;:::-;;:::i;33033:202::-;33118:4;33141:47;;;33156:32;33141:47;;:87;;-1:-1:-1;24946:25:0;24931:40;;;;33192:36;33134:94;33033:202;-1:-1:-1;;33033:202:0:o;42828:348::-;41190:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41159:71;;;;;;;9425:2:1;41159:71:0;;;9407:21:1;9464:2;9444:18;;;9437:30;9503:26;9483:18;;;9476:54;9547:18;;41159:71:0;;;;;;;;;-1:-1:-1;;;;;42941:19:0;::::1;42921:17;42941:19:::0;;;:12:::1;:19;::::0;;;;;;42974:14;;;42970:27:::1;;42990:7;42828:348:::0;;:::o;42970:27::-:1;-1:-1:-1::0;;;;;43038:19:0;::::1;43060:1;43038:19:::0;;;:12:::1;:19;::::0;;;;:23;43071:45:::1;::::0;43095:9;43106;43071:23:::1;:45::i;:::-;43131:38;::::0;;-1:-1:-1;;;;;9857:15:1;;;9839:34;;9909:15;;9904:2;9889:18;;9882:43;9941:18;;;9934:34;;;43131:38:0::1;::::0;9766:2:1;9751:18;43131:38:0::1;;;;;;;42911:265;41240:1;42828:348:::0;;:::o;34694:136::-;34343:7;34369:12;;;;;;;;;;:22;;;32932:16;32943:4;32932:10;:16::i;:::-;34798:25:::1;34809:4;34815:7;34798:10;:25::i;:::-;;34694:136:::0;;;:::o;35796:245::-;-1:-1:-1;;;;;35889:34:0;;22980:10;35889:34;35885:102;;35946:30;;;;;;;;;;;;;;35885:102;35997:37;36009:4;36015:18;35997:11;:37::i;:::-;;35796:245;;:::o;42127:199::-;42222:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;42186:48;;;;;;42244:36;40398:26;42270:9;42244:10;:36::i;:::-;-1:-1:-1;42295:24:0;;-1:-1:-1;;;;;10143:55:1;;10125:74;;42295:24:0;;10113:2:1;10098:18;42295:24:0;;;;;;;;42127:199;:::o;52078:1135::-;41062:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41032:69;;;;;;;10412:2:1;41032:69:0;;;10394:21:1;10451:2;10431:18;;;10424:30;10490:25;10470:18;;;10463:53;10533:18;;41032:69:0;10210:347:1;41032:69:0;52182:18;;::::1;::::0;::::1;::::0;52158:21:::1;52249:29;52192:7:::0;52249:20:::1;:29::i;:::-;52210:68:::0;-1:-1:-1;52396:27:0::1;52363:29;::::0;;;:14:::1;:29;::::0;;;;;;;;::::1;;::::0;:60;::::1;;;;;;:::i;:::-;;52359:90;;52432:17;;;;;;;;;;;;;;52359:90;52460:24;52487:27:::0;;;:12:::1;:27;::::0;;;;;;;;52460:54;;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;;;;::::1;-1:-1:-1::0;;;;;52460:54:0::1;::::0;;::::1;::::0;;;52545:10:::1;52528:27;52524:57;;52564:17;;;;;;;;;;;;;;52524:57;51597:15:::0;;43687:10:::1;::::0;51578:15;51571:41;51563:49;;52595:35:::1;52591:72;;52639:24;;;;;;;;;;;;;;52591:72;52674:29;::::0;;;:14:::1;:29;::::0;;;;:60;;-1:-1:-1;;52674:60:0::1;52706:28;52674:60;::::0;;52809:27:::1;::::0;::::1;::::0;:31;52805:105:::1;;52883:27;::::0;::::1;::::0;52855:23:::1;::::0;::::1;::::0;-1:-1:-1;;;;;52842:37:0::1;;::::0;;;:12:::1;:37;::::0;;;;:68;;:37;;;:68:::1;::::0;52883:27;;52842:68:::1;:::i;:::-;::::0;;;-1:-1:-1;;52805:105:0::1;53005:23;::::0;::::1;::::0;53055:24:::1;::::0;::::1;::::0;53089:35:::1;-1:-1:-1::0;;;;;53089:23:0;::::1;53113:2:::0;53055:24;53089:23:::1;:35::i;:::-;53140:66;::::0;;-1:-1:-1;;;;;11073:55:1;;;11055:74;;11160:2;11145:18;;11138:34;;;53140:66:0;::::1;::::0;53176:10:::1;::::0;53161:13;;53140:66:::1;::::0;11028:18:1;53140:66:0::1;;;;;;;;52148:1065;;;;;52078:1135:::0;;:::o;46321:2114::-;46448:13;46427:6;:17;;;:34;;;46423:63;;46470:16;;;;;;;;;;;;;;46423:63;46500:19;;;;:24;;:50;;-1:-1:-1;46528:17:0;;;;:22;46500:50;46496:80;;;46559:17;;;;;;;;;;;;;;46496:80;46590:18;;;;-1:-1:-1;;;;;46590:32:0;;;:66;;-1:-1:-1;46626:16:0;;;;-1:-1:-1;;;;;46626:30:0;;46590:66;46586:92;;;46665:13;;;;;;;;;;;;;;46586:92;46710:37;43964:10;46710:15;:37;:::i;:::-;46692:6;:15;;;:55;46688:86;;;46756:18;;;;;;;;;;;;;;46688:86;46909:20;46932:66;46951:4;46958:6;:18;;;46978:6;:19;;;46932:10;:66::i;:::-;46909:89;;47066:23;47121:1;47103:15;;:19;47099:85;;;40465:3;47158:15;;47143:12;:30;;;;:::i;:::-;47142:42;;;;:::i;:::-;47124:60;;47099:85;47194:31;47210:15;47194:31;;:::i;:::-;;;47338:20;47385:618;;;;;;;;47443:13;47385:618;;;;;;47488:6;:17;;;47385:618;;;;;;47537:6;:13;;;-1:-1:-1;;;;;47385:618:0;;;;;47583:6;:9;;;-1:-1:-1;;;;;47385:618:0;;;;;47623:6;:18;;;-1:-1:-1;;;;;47385:618:0;;;;;47670:6;:16;;;-1:-1:-1;;;;;47385:618:0;;;;;47718:12;47385:618;;;;47760:6;:17;;;47385:618;;;;47812:15;47385:618;;;;47859:6;:19;;;47385:618;;;;;;47906:6;:15;;;47385:618;;;;47946:5;;:7;;;;;;;;;:::i;:::-;;;;-1:-1:-1;47385:618:0;;47361:652;;;;;;;;:::i;:::-;;;;;;;;;;;;;;48047:18;;47361:652;48047:18;;;;;;;48023:21;48075:29;;;:14;:29;;;;;;:54;;-1:-1:-1;;48075:54:0;48107:22;48075:54;;;48201:13;;;48249:17;;48280:18;;;;48312:16;;;;48368:17;;;;48399:19;;;;47361:652;;-1:-1:-1;48047:18:0;;-1:-1:-1;;;;;48145:283:0;;;;48047:18;;48145:283;;;;47361:652;;48249:17;;48280:18;;48312:16;;48342:12;;48145:283;:::i;:::-;;;;;;;;46382:2053;;;;46321:2114;:::o;53803:915::-;53884:18;;;;;;53860:21;53951:29;53894:7;53951:20;:29::i;:::-;53912:68;;43821:10;54069:11;:20;;;:35;;;;:::i;:::-;54050:15;:54;54046:88;;54113:21;;;;;;;;;;;;;;54046:88;54244:22;54211:29;;;;:14;:29;;;;;;;;;;;;:55;;;;;;;:::i;:::-;;54207:85;;54275:17;;;;;;;;;;;;;;54207:85;54302:29;;;;54334:21;54302:29;;;;;;;;:53;;-1:-1:-1;;54302:53:0;;54334:21;54302:53;;;;-1:-1:-1;54441:24:0;;;;54491:23;;;;54568:27;;;;54541:24;;;;54428:10;;54541:54;;;:::i;:::-;54524:71;-1:-1:-1;54605:35:0;-1:-1:-1;;;;;54605:23:0;;54629:2;54524:71;54605:23;:35::i;:::-;54656:55;;;-1:-1:-1;;;;;11073:55:1;;;11055:74;;11160:2;11145:18;;11138:34;;;54656:55:0;;;54678:13;;54656:55;;11028:18:1;54656:55:0;;;;;;;53850:868;;;;;53803:915;:::o;41542:199::-;41638:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41602:48;;;;;;41660:35;40261:25;41686:8;41660:11;:35::i;:::-;-1:-1:-1;41710:24:0;;-1:-1:-1;;;;;10143:55:1;;10125:74;;41710:24:0;;10113:2:1;10098:18;41710:24:0;9979:226:1;41747:181:0;41836:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41800:48;;;;;;41858:30;40329:23;41881:6;41858:10;:30::i;:::-;-1:-1:-1;41903:18:0;;-1:-1:-1;;;;;10143:55:1;;10125:74;;41903:18:0;;10113:2:1;10098:18;41903::0;9979:226:1;50218:793:0;41062:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41032:69;;;;;;;10412:2:1;41032:69:0;;;10394:21:1;10451:2;10431:18;;;10424:30;10490:25;10470:18;;;10463:53;10533:18;;41032:69:0;10210:347:1;41032:69:0;50330:18;;::::1;::::0;::::1;::::0;50306:21:::1;50397:29;50340:7:::0;50397:20:::1;:29::i;:::-;50358:68;;43821:10;50522:11;:20;;;:35;;;;:::i;:::-;50504:15;:53;50500:84;;;50566:18;;;;;;;;;;;;;;50500:84;50688:22;50655:29;::::0;;;:14:::1;:29;::::0;;;;;;;;::::1;;::::0;:55;::::1;;;;;;:::i;:::-;;50651:85;;50719:17;;;;;;;;;;;;;;50651:85;50746:29;::::0;;;:14:::1;:29;::::0;;;;;;;:59;;50778:27:::1;-1:-1:-1::0;;50746:59:0;;::::1;;::::0;;50845:70;;;;::::1;::::0;;::::1;50876:15;50845:70:::0;::::1;::::0;;50903:10:::1;50845:70:::0;;::::1;::::0;;;50815:27;;;:12:::1;:27:::0;;;;;;:100;;;;-1:-1:-1;;;;;50815:100:0::1;::::0;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;50946:58;785:25:1;;;50746:29:0;;50946:58:::1;::::0;758:18:1;50946:58:0::1;;;;;;;50296:715;;50218:793:::0;;:::o;48473:1707::-;41062:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41032:69;;;;;;;10412:2:1;41032:69:0;;;10394:21:1;10451:2;10431:18;;;10424:30;10490:25;10470:18;;;10463:53;10533:18;;41032:69:0;10210:347:1;41032:69:0;48573:18;;::::1;::::0;::::1;::::0;48549:21:::1;48640:29;48583:7:::0;48640:20:::1;:29::i;:::-;48601:68;;48717:13;48683:48;;:11;:23;;;:48;;;48679:77;;48740:16;;;;;;;;;;;;;;48679:77;48852:11;:20;;;48834:15;:38;48830:69;;;48881:18;;;;;;;;;;;;;;48830:69;48960:27;::::0;;;:12:::1;:27;::::0;;;;;::::1;;48956:60;;;48996:20;;;;;;;;;;;;;;48956:60;49026:27;::::0;;;:12:::1;:27;::::0;;;;:34;;-1:-1:-1;;49026:34:0::1;49056:4;49026:34;::::0;;49173:25:::1;::::0;::::1;::::0;49224:21:::1;::::0;::::1;::::0;49272:22:::1;::::0;::::1;::::0;49322:14:::1;::::0;49351:24:::1;::::0;::::1;::::0;49346:517:::1;;-1:-1:-1::0;49429:1:0::1;49444:29;49455:2:::0;49459:5;49466:6;49444:10:::1;:29::i;:::-;;49346:517;;;49494:38:::0;-1:-1:-1;;;;;49494:38:0;::::1;::::0;49490:373:::1;;49614:38;49625:2:::0;49629:5;49636:15:::1;49645:6:::0;49636;:15:::1;:::i;:::-;49614:10;:38::i;49490:373::-;49756:29;49767:2;49771:5;49778:6;49756:10;:29::i;:::-;;49799:53;49810:2;37662:42;49845:6;49799:10;:53::i;:::-;;49490:373;49972:25:::0;;50011:23:::1;::::0;;::::1;::::0;50048:21:::1;::::0;;::::1;::::0;50083:24:::1;::::0;;::::1;::::0;50121:22:::1;::::0;::::1;::::0;49878:295:::1;::::0;;13557:10:1;13545:23;;;13527:42;;-1:-1:-1;;;;;13666:15:1;;;13661:2;13646:18;;13639:43;13718:15;;;13698:18;;;13691:43;;;;13765:2;13750:18;;13743:34;13793:19;;;13786:35;13837:19;;13830:35;;;49878:295:0;::::1;::::0;49932:10:::1;::::0;49905:13;;49878:295:::1;::::0;13499:19:1;49878:295:0::1;13242:629:1::0;51667:373:0;51748:4;51801:27;51768:29;;;;:14;:29;;;;;;;;;;;;:60;;;;;;;:::i;:::-;;51764:90;;51837:17;;;;;;;;;;;;;;51764:90;51864:24;51891:27;;;:12;:27;;;;;;;;;51864:54;;;;;;;;;;;;;;-1:-1:-1;;;;;51864:54:0;;;;;;;;;;;;51932:24;;;51928:54;;51965:17;;;;;;;;;;;;;;51928:54;51597:15;;43687:10;;51578:15;51571:41;51563:49;;51999:34;;51667:373;-1:-1:-1;;;;51667:373:0:o;46120:163::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46236:40:0;;-1:-1:-1;;46236:40:0;;;;;;;;;;:::i;53251:514::-;40938:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;40910:65;;;;;;;15688:2:1;40910:65:0;;;15670:21:1;15727:2;15707:18;;;15700:30;15766:23;15746:18;;;15739:51;15807:18;;40910:65:0;15486:345:1;40910:65:0;53357:27:::1;53324:29;::::0;;;:14:::1;:29;::::0;;;;;;;;::::1;;::::0;:60;::::1;;;;;;:::i;:::-;;53320:90;;53393:17;;;;;;;;;;;;;;53320:90;53435:27;::::0;;;:12:::1;:27;::::0;;;;;;;;53424:39;;;;::::1;::::0;;;;::::1;::::0;;::::1;::::0;;;;;;::::1;-1:-1:-1::0;;;;;53424:39:0::1;::::0;;;::::1;::::0;;;;43687:10:::1;::::0;51578:15;51571:41;51563:49;53424:56:::1;53420:90;;;53489:21;;;;;;;;;;;;;;53420:90;53598:29;::::0;;;:14:::1;:29;::::0;;;;;;;:54;;-1:-1:-1;;53598:54:0::1;53630:22;53598:54;::::0;;53669:12:::1;:27:::0;;;;;;53662:34;;;53712:46;53747:10:::1;::::0;53598:29;;53712:46:::1;::::0;53598:29;53712:46:::1;53251:514:::0;:::o;42543:279::-;41190:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41159:71;;;;;;;9425:2:1;41159:71:0;;;9407:21:1;9464:2;9444:18;;;9437:30;9503:26;9483:18;;;9476:54;9547:18;;41159:71:0;9223:348:1;41159:71:0;40513:6:::1;42631:10;:26;;42623:55;;;::::0;::::1;::::0;;16038:2:1;42623:55:0::1;::::0;::::1;16020:21:1::0;16077:2;16057:18;;;16050:30;16116:18;16096;;;16089:46;16152:18;;42623:55:0::1;15836:340:1::0;42623:55:0::1;42709:15;::::0;;42734:28;;;;42777:38:::1;::::0;;16355:25:1;;;16411:2;16396:18;;16389:34;;;42777:38:0::1;::::0;16328:18:1;42777:38:0::1;;;;;;;;42613:209;42543:279:::0;:::o;43182:253::-;41190:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41159:71;;;;;;;9425:2:1;41159:71:0;;;9407:21:1;9464:2;9444:18;;;9437:30;9503:26;9483:18;;;9476:54;9547:18;;41159:71:0;9223:348:1;41159:71:0;43296:14:::1;::::0;;43320:34;;;;43369:59:::1;::::0;;16355:25:1;;;16411:2;16396:18;;16389:34;;;43369:59:0::1;::::0;16328:18:1;43369:59:0::1;16181:248:1::0;41934:187:0;42026:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41990:48;;;;;;42048:31;40329:23;42072:6;42048:11;:31::i;:::-;-1:-1:-1;42094:20:0;;-1:-1:-1;;;;;10143:55:1;;10125:74;;42094:20:0;;10113:2:1;10098:18;42094:20:0;9979:226:1;35110:138:0;34343:7;34369:12;;;;;;;;;;:22;;;32932:16;32943:4;32932:10;:16::i;:::-;35215:26:::1;35227:4;35233:7;35215:11;:26::i;41343:193::-:0;41436:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41400:48;;;;;;41458:34;40261:25;41483:8;41458:10;:34::i;:::-;-1:-1:-1;41507:22:0;;-1:-1:-1;;;;;10143:55:1;;10125:74;;41507:22:0;;10113:2:1;10098:18;41507:22:0;9979:226:1;42332:205:0;42430:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;42394:48;;;;;;42452:37;40398:26;42479:9;42452:11;:37::i;:::-;-1:-1:-1;42504:26:0;;-1:-1:-1;;;;;10143:55:1;;10125:74;;42504:26:0;;10113:2:1;10098:18;42504:26:0;9979:226:1;37945:653:0;38120:4;-1:-1:-1;;;;;38106:19:0;;;38102:32;;37945:653;;;:::o;38102:32::-;38206:5;38215:1;38206:10;38202:23;;37945:653;;;:::o;38202:23::-;38238:20;-1:-1:-1;;;;;38238:20:0;;;38234:358;;38418:12;38435:2;-1:-1:-1;;;;;38435:7:0;38450:5;38435:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38417:43;;;38482:7;38474:39;;;;;;;16846:2:1;38474:39:0;;;16828:21:1;16885:2;16865:18;;;16858:30;16924:21;16904:18;;;16897:49;16963:18;;38474:39:0;16644:343:1;38234:358:0;38544:37;-1:-1:-1;;;;;38544:26:0;;38571:2;38575:5;38544:26;:37::i;33667:103::-;33733:30;33744:4;22980:10;33733;:30::i;:::-;33667:103;:::o;36647:316::-;36724:4;33422:12;;;;;;;;;;;-1:-1:-1;;;;;33422:29:0;;;;;;;;;;;;36740:217;;36783:6;:12;;;;;;;;;;;-1:-1:-1;;;;;36783:29:0;;;;;;;;;:36;;-1:-1:-1;;36783:36:0;36815:4;36783:36;;;36865:12;22980:10;;22901:96;36865:12;-1:-1:-1;;;;;36838:40:0;36856:7;-1:-1:-1;;;;;36838:40:0;36850:4;36838:40;;;;;;;;;;-1:-1:-1;36899:4:0;36892:11;;36740:217;-1:-1:-1;36941:5:0;36934:12;;37198:317;37276:4;33422:12;;;;;;;;;;;-1:-1:-1;;;;;33422:29:0;;;;;;;;;;;;37292:217;;;37366:5;37334:12;;;;;;;;;;;-1:-1:-1;;;;;37334:29:0;;;;;;;;;;:37;;-1:-1:-1;;37334:37:0;;;37390:40;22980:10;;37334:12;;37390:40;;37366:5;37390:40;-1:-1:-1;37451:4:0;37444:11;;44905:1177;44993:20;-1:-1:-1;;;;;45029:38:0;;37662:42;45029:38;45025:1051;;45083:24;:5;-1:-1:-1;;;;;45083:22:0;;:24::i;:::-;45188:34;;;;;-1:-1:-1;;;;;10143:55:1;;;45188:34:0;;;10125:74:1;45188:23:0;;;;;10098:18:1;;45188:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;45173:49;-1:-1:-1;45368:61:0;-1:-1:-1;;;;;45368:30:0;;45399:10;45411:9;45422:6;45368:30;:61::i;:::-;45565:34;;;;;-1:-1:-1;;;;;10143:55:1;;;45565:34:0;;;10125:74:1;45602:12:0;;45565:23;;;;;;10098:18:1;;45565:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:49;;;;:::i;:::-;45550:64;;45025:1051;;;45736:9;45726:6;:19;45722:51;;45754:19;;;;;;;;;;;;;;45722:51;-1:-1:-1;;;;;45854:26:0;;45875:4;45854:26;45850:74;;45882:42;-1:-1:-1;;;;;45882:23:0;;45906:9;45917:6;45882:23;:42::i;:::-;-1:-1:-1;46056:9:0;45025:1051;44905:1177;;;;;:::o;26150:160::-;26259:43;;-1:-1:-1;;;;;11073:55:1;;;26259:43:0;;;11055:74:1;11145:18;;;11138:34;;;26232:71:0;;26252:5;;26274:14;;;;;11028:18:1;;26259:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26232:19;:71::i;33900:197::-;33399:4;33422:12;;;;;;;;;;;-1:-1:-1;;;;;33422:29:0;;;;;;;;;;;;33983:108;;34033:47;;;;;-1:-1:-1;;;;;11073:55:1;;34033:47:0;;;11055:74:1;11145:18;;;11138:34;;;11028:18;;34033:47:0;10881:297:1;39762:344:0;39929:38;-1:-1:-1;;;;;39929:38:0;;;39925:69;;39976:18;;;;;;;;;;;;;;39925:69;40050:5;-1:-1:-1;;;;;40050:17:0;;40071:1;40050:22;40046:53;;40081:18;;;;;;;;;;;;;;26549:188;26676:53;;-1:-1:-1;;;;;9857:15:1;;;26676:53:0;;;9839:34:1;9909:15;;;9889:18;;;9882:43;9941:18;;;9934:34;;;26649:81:0;;26669:5;;26691:18;;;;;9751::1;;26676:53:0;9576:398:1;28906:629:0;29325:23;29351:33;-1:-1:-1;;;;;29351:27:0;;29379:4;29351:27;:33::i;:::-;29325:59;;29398:10;:17;29419:1;29398:22;;:57;;;;;29436:10;29425:30;;;;;;;;;;;;:::i;:::-;29424:31;29398:57;29394:135;;;29478:40;;;;;-1:-1:-1;;;;;10143:55:1;;29478:40:0;;;10125:74:1;10098:18;;29478:40:0;9979:226:1;18686:151:0;18761:12;18792:38;18814:6;18822:4;18828:1;18761:12;19402;19416:23;19443:6;-1:-1:-1;;;;;19443:11:0;19462:5;19469:4;19443:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19401:73;;;;19491:55;19518:6;19526:7;19535:10;19491:26;:55::i;:::-;19484:62;19161:392;-1:-1:-1;;;;;;19161:392:0:o;20606:582::-;20750:12;20779:7;20774:408;;20802:19;20810:10;20802:7;:19::i;:::-;20774:408;;;21026:17;;:22;:49;;;;-1:-1:-1;;;;;;21052:18:0;;;:23;21026:49;21022:119;;;21102:24;;;;;-1:-1:-1;;;;;10143:55:1;;21102:24:0;;;10125:74:1;10098:18;;21102:24:0;9979:226:1;21022:119:0;-1:-1:-1;21161:10:0;21154:17;;21724:516;21855:17;;:21;21851:383;;22083:10;22077:17;22139:15;22126:10;22122:2;22118:19;22111:44;21851:383;22206:17;;;;;;;;;;;;;;14:332:1;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;180:9;167:23;230:66;223:5;219:78;212:5;209:89;199:117;;312:1;309;302:12;821:180;880:6;933:2;921:9;912:7;908:23;904:32;901:52;;;949:1;946;939:12;901:52;-1:-1:-1;972:23:1;;821:180;-1:-1:-1;821:180:1:o;1006:184::-;1058:77;1055:1;1048:88;1155:4;1152:1;1145:15;1179:4;1176:1;1169:15;1195:402;1344:2;1329:18;;1377:1;1366:13;;1356:201;;1413:77;1410:1;1403:88;1514:4;1511:1;1504:15;1542:4;1539:1;1532:15;1356:201;1566:25;;;1195:402;:::o;1602:154::-;-1:-1:-1;;;;;1681:5:1;1677:54;1670:5;1667:65;1657:93;;1746:1;1743;1736:12;1761:134;1829:20;;1858:31;1829:20;1858:31;:::i;:::-;1761:134;;;:::o;1900:388::-;1968:6;1976;2029:2;2017:9;2008:7;2004:23;2000:32;1997:52;;;2045:1;2042;2035:12;1997:52;2084:9;2071:23;2103:31;2128:5;2103:31;:::i;:::-;2153:5;-1:-1:-1;2210:2:1;2195:18;;2182:32;2223:33;2182:32;2223:33;:::i;:::-;2275:7;2265:17;;;1900:388;;;;;:::o;2475:315::-;2543:6;2551;2604:2;2592:9;2583:7;2579:23;2575:32;2572:52;;;2620:1;2617;2610:12;2572:52;2656:9;2643:23;2633:33;;2716:2;2705:9;2701:18;2688:32;2729:31;2754:5;2729:31;:::i;2795:247::-;2854:6;2907:2;2895:9;2886:7;2882:23;2878:32;2875:52;;;2923:1;2920;2913:12;2875:52;2962:9;2949:23;2981:31;3006:5;2981:31;:::i;3047:184::-;3099:77;3096:1;3089:88;3196:4;3193:1;3186:15;3220:4;3217:1;3210:15;3236:252;3308:2;3302:9;3350:3;3338:16;;3384:18;3369:34;;3405:22;;;3366:62;3363:88;;;3431:18;;:::i;:::-;3467:2;3460:22;3236:252;:::o;3493:247::-;3560:2;3554:9;3602:3;3590:16;;3636:18;3621:34;;3657:22;;;3618:62;3615:88;;;3683:18;;:::i;3745:777::-;3787:5;3840:3;3833:4;3825:6;3821:17;3817:27;3807:55;;3858:1;3855;3848:12;3807:55;3894:6;3881:20;3920:18;3957:2;3953;3950:10;3947:36;;;3963:18;;:::i;:::-;4097:2;4091:9;4159:4;4151:13;;4002:66;4147:22;;;4171:2;4143:31;4139:40;4127:53;;;4195:18;;;4215:22;;;4192:46;4189:72;;;4241:18;;:::i;:::-;4281:10;4277:2;4270:22;4316:2;4308:6;4301:18;4362:3;4355:4;4350:2;4342:6;4338:15;4334:26;4331:35;4328:55;;;4379:1;4376;4369:12;4328:55;4443:2;4436:4;4428:6;4424:17;4417:4;4409:6;4405:17;4392:54;4490:1;4483:4;4478:2;4470:6;4466:15;4462:26;4455:37;4510:6;4501:15;;;;;;3745:777;;;;:::o;4527:455::-;4604:6;4612;4665:2;4653:9;4644:7;4640:23;4636:32;4633:52;;;4681:1;4678;4671:12;4633:52;4721:9;4708:23;4754:18;4746:6;4743:30;4740:50;;;4786:1;4783;4776:12;4740:50;4809:49;4850:7;4841:6;4830:9;4826:22;4809:49;:::i;:::-;4799:59;;;4908:2;4897:9;4893:18;4880:32;4921:31;4946:5;4921:31;:::i;4987:121::-;5072:10;5065:5;5061:22;5054:5;5051:33;5041:61;;5098:1;5095;5088:12;5113:132;5180:20;;5209:30;5180:20;5209:30;:::i;5250:118::-;5336:5;5329:13;5322:21;5315:5;5312:32;5302:60;;5358:1;5355;5348:12;5373:128;5438:20;;5467:28;5438:20;5467:28;:::i;5506:865::-;5594:6;5647:3;5635:9;5626:7;5622:23;5618:33;5615:53;;;5664:1;5661;5654:12;5615:53;5690:22;;:::i;:::-;5735:28;5753:9;5735:28;:::i;:::-;5728:5;5721:43;5796:38;5830:2;5819:9;5815:18;5796:38;:::i;:::-;5791:2;5784:5;5780:14;5773:62;5867:38;5901:2;5890:9;5886:18;5867:38;:::i;:::-;5862:2;5855:5;5851:14;5844:62;5938:38;5972:2;5961:9;5957:18;5938:38;:::i;:::-;5933:2;5926:5;5922:14;5915:62;6010:39;6044:3;6033:9;6029:19;6010:39;:::i;:::-;6004:3;5997:5;5993:15;5986:64;6111:3;6100:9;6096:19;6083:33;6077:3;6070:5;6066:15;6059:58;6178:3;6167:9;6163:19;6150:33;6144:3;6137:5;6133:15;6126:58;6217:36;6248:3;6237:9;6233:19;6217:36;:::i;:::-;6211:3;6200:15;;6193:61;6273:3;6321:18;;;6308:32;6292:14;;;6285:56;;;;-1:-1:-1;6204:5:1;5506:865;-1:-1:-1;5506:865:1:o;6376:320::-;6444:6;6497:2;6485:9;6476:7;6472:23;6468:32;6465:52;;;6513:1;6510;6503:12;6465:52;6553:9;6540:23;6586:18;6578:6;6575:30;6572:50;;;6618:1;6615;6608:12;6572:50;6641:49;6682:7;6673:6;6662:9;6658:22;6641:49;:::i;:::-;6631:59;6376:320;-1:-1:-1;;;;6376:320:1:o;6701:388::-;6778:6;6786;6839:2;6827:9;6818:7;6814:23;6810:32;6807:52;;;6855:1;6852;6845:12;6807:52;6895:9;6882:23;6928:18;6920:6;6917:30;6914:50;;;6960:1;6957;6950:12;6914:50;6983:49;7024:7;7015:6;7004:9;7000:22;6983:49;:::i;:::-;6973:59;7079:2;7064:18;;;;7051:32;;-1:-1:-1;;;;6701:388:1:o;7658:1375::-;7891:13;;7635:10;7624:22;7612:35;;7860:3;7845:19;;7963:4;7955:6;7951:17;7945:24;7978:53;8025:4;8014:9;8010:20;7996:12;7635:10;7624:22;7612:35;;7559:94;7978:53;;8080:4;8072:6;8068:17;8062:24;8095:56;8145:4;8134:9;8130:20;8114:14;-1:-1:-1;;;;;7160:54:1;7148:67;;7094:127;8095:56;;8200:4;8192:6;8188:17;8182:24;8215:56;8265:4;8254:9;8250:20;8234:14;-1:-1:-1;;;;;7160:54:1;7148:67;;7094:127;8215:56;;8320:4;8312:6;8308:17;8302:24;8335:56;8385:4;8374:9;8370:20;8354:14;-1:-1:-1;;;;;7160:54:1;7148:67;;7094:127;8335:56;;8440:4;8432:6;8428:17;8422:24;8455:56;8505:4;8494:9;8490:20;8474:14;-1:-1:-1;;;;;7160:54:1;7148:67;;7094:127;8455:56;;8567:4;8559:6;8555:17;8549:24;8542:4;8531:9;8527:20;8520:54;8630:4;8622:6;8618:17;8612:24;8605:4;8594:9;8590:20;8583:54;8656:6;8716:2;8708:6;8704:15;8698:22;8693:2;8682:9;8678:18;8671:50;;8740:6;8795:2;8787:6;8783:15;8777:22;8808:51;8855:2;8844:9;8840:18;8824:14;421:13;414:21;402:34;;351:91;8808:51;-1:-1:-1;;8878:6:1;8926:15;;;8920:22;8900:18;;;8893:50;8962:6;9010:15;;;9004:22;8984:18;;;;8977:50;;;;7658:1375;:::o;10562:184::-;10614:77;10611:1;10604:88;10711:4;10708:1;10701:15;10735:4;10732:1;10725:15;10751:125;10816:9;;;10837:10;;;10834:36;;;10850:18;;:::i;11183:168::-;11256:9;;;11287;;11304:15;;;11298:22;;11284:37;11274:71;;11325:18;;:::i;11356:274::-;11396:1;11422;11412:189;;11457:77;11454:1;11447:88;11558:4;11555:1;11548:15;11586:4;11583:1;11576:15;11412:189;-1:-1:-1;11615:9:1;;11356:274::o;11635:128::-;11702:9;;;11723:11;;;11720:37;;;11737:18;;:::i;11768:195::-;11807:3;11838:66;11831:5;11828:77;11825:103;;11908:18;;:::i;:::-;-1:-1:-1;11955:1:1;11944:13;;11768:195::o;11968:250::-;12053:1;12063:113;12077:6;12074:1;12071:13;12063:113;;;12153:11;;;12147:18;12134:11;;;12127:39;12099:2;12092:10;12063:113;;;-1:-1:-1;;12210:1:1;12192:16;;12185:27;11968:250::o;12223:1014::-;12530:3;12519:9;12512:22;12493:4;12563:6;12557:13;12607:6;12601:3;12590:9;12586:19;12579:35;12633:3;12645:81;12719:6;12714:2;12703:9;12699:18;12692:4;12684:6;12680:17;12645:81;:::i;:::-;12906:10;12894:23;;;;12887:4;12872:20;;12865:53;-1:-1:-1;;;;;13015:15:1;;;13010:2;12995:18;;12988:43;13067:15;;;;13062:2;13047:18;;13040:43;13114:3;13099:19;;13092:35;;;;13158:3;13143:19;;13136:35;;;;13215:14;13208:22;13202:3;13187:19;;13180:51;12778:2;12766:15;;;-1:-1:-1;12762:88:1;12747:104;12743:113;;;;;-1:-1:-1;;12223:1014:1:o;13876:136::-;13954:13;;13976:30;13954:13;13976:30;:::i;14017:138::-;14096:13;;14118:31;14096:13;14118:31;:::i;14160:132::-;14236:13;;14258:28;14236:13;14258:28;:::i;14297:1184::-;14401:6;14454:3;14442:9;14433:7;14429:23;14425:33;14422:53;;;14471:1;14468;14461:12;14422:53;14497:17;;:::i;:::-;14537:39;14566:9;14537:39;:::i;:::-;14530:5;14523:54;14609:48;14653:2;14642:9;14638:18;14609:48;:::i;:::-;14604:2;14597:5;14593:14;14586:72;14690:49;14735:2;14724:9;14720:18;14690:49;:::i;:::-;14685:2;14678:5;14674:14;14667:73;14772:49;14817:2;14806:9;14802:18;14772:49;:::i;:::-;14767:2;14760:5;14756:14;14749:73;14855:50;14900:3;14889:9;14885:19;14855:50;:::i;:::-;14849:3;14842:5;14838:15;14831:75;14939:50;14984:3;14973:9;14969:19;14939:50;:::i;:::-;14933:3;14926:5;14922:15;14915:75;15044:3;15033:9;15029:19;15023:26;15017:3;15010:5;15006:15;14999:51;15104:3;15093:9;15089:19;15083:26;15077:3;15070:5;15066:15;15059:51;15129:3;15185:2;15174:9;15170:18;15164:25;15159:2;15152:5;15148:14;15141:49;;15209:3;15244:46;15286:2;15275:9;15271:18;15244:46;:::i;:::-;15228:14;;;15221:70;15310:3;15351:18;;;15345:25;15329:14;;;15322:49;15390:3;15431:18;;;15425:25;15409:14;;;15402:49;;;;-1:-1:-1;15232:5:1;14297:1184;-1:-1:-1;14297:1184:1:o;16992:184::-;17062:6;17115:2;17103:9;17094:7;17090:23;17086:32;17083:52;;;17131:1;17128;17121:12;17083:52;-1:-1:-1;17154:16:1;;16992:184;-1:-1:-1;16992:184:1:o;17483:245::-;17550:6;17603:2;17591:9;17582:7;17578:23;17574:32;17571:52;;;17619:1;17616;17609:12;17571:52;17651:9;17645:16;17670:28;17692:5;17670:28;:::i;17733:287::-;17862:3;17900:6;17894:13;17916:66;17975:6;17970:3;17963:4;17955:6;17951:17;17916:66;:::i;:::-;17998:16;;;;;17733:287;-1:-1:-1;;17733:287:1:o","abiDefinition":[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"AmountIncorrect","type":"error"},{"inputs":[],"name":"ChainIncorrect","type":"error"},{"inputs":[],"name":"DeadlineExceeded","type":"error"},{"inputs":[],"name":"DeadlineNotExceeded","type":"error"},{"inputs":[],"name":"DeadlineTooShort","type":"error"},{"inputs":[],"name":"DisputePeriodNotPassed","type":"error"},{"inputs":[],"name":"DisputePeriodPassed","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"MsgValueIncorrect","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"SenderIncorrect","type":"error"},{"inputs":[],"name":"StatusIncorrect","type":"error"},{"inputs":[],"name":"TokenNotContract","type":"error"},{"inputs":[],"name":"TransactionRelayed","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositRefunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"}],"name":"BridgeProofDisputed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":false,"internalType":"bytes32","name":"transactionHash","type":"bytes32"}],"name":"BridgeProofProvided","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint32","name":"originChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"chainGasAmount","type":"uint256"}],"name":"BridgeRelayed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes","name":"request","type":"bytes"},{"indexed":false,"internalType":"uint32","name":"destChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"sendChainGas","type":"bool"}],"name":"BridgeRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldChainGasAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"ChainGasAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFeeRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"FeeRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesSwept","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"governor","type":"address"}],"name":"GovernorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"governor","type":"address"}],"name":"GovernorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guard","type":"address"}],"name":"GuardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guard","type":"address"}],"name":"GuardRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DISPUTE_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_RATE_MAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GOVERNOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GUARD_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_DEADLINE_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROVE_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAYER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_governor","type":"address"}],"name":"addGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guard","type":"address"}],"name":"addGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_relayer","type":"address"}],"name":"addRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstChainId","type":"uint32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IFastBridge.BridgeParams","name":"params","type":"tuple"}],"name":"bridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"bridgeProofs","outputs":[{"internalType":"uint96","name":"timestamp","type":"uint96"},{"internalType":"address","name":"relayer","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"bridgeRelays","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"bridgeStatuses","outputs":[{"internalType":"enum FastBridge.BridgeStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"address","name":"relayer","type":"address"}],"name":"canClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainGasAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"address","name":"to","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deployBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"dispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"getBridgeTransaction","outputs":[{"components":[{"internalType":"uint32","name":"originChainId","type":"uint32"},{"internalType":"uint32","name":"destChainId","type":"uint32"},{"internalType":"address","name":"originSender","type":"address"},{"internalType":"address","name":"destRecipient","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256","name":"originFeeAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct IFastBridge.BridgeTransaction","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"protocolFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"bytes32","name":"destTxHash","type":"bytes32"}],"name":"prove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"relay","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_governor","type":"address"}],"name":"removeGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guard","type":"address"}],"name":"removeGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_relayer","type":"address"}],"name":"removeRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"setChainGasAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"setProtocolFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"sweepProtocolFees","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"DISPUTE_PERIOD()":{"notice":"Dispute period for relayed transactions"},"MIN_DEADLINE_PERIOD()":{"notice":"Minimum deadline period to relay a requested bridge transaction"},"PROVE_PERIOD()":{"notice":"Prove period added to deadline period for proven transactions"},"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"notice":"Initiates bridge on origin chain to be relayed by off-chain relayer"},"bridgeProofs(bytes32)":{"notice":"Proof of relayed bridge tx on origin chain"},"bridgeRelays(bytes32)":{"notice":"Whether bridge has been relayed on destination chain"},"bridgeStatuses(bytes32)":{"notice":"Status of the bridge tx on origin chain"},"canClaim(bytes32,address)":{"notice":"Checks if the dispute period has passed so bridge deposit can be claimed"},"chainGasAmount()":{"notice":"Chain gas amount to forward as rebate if requested"},"claim(bytes,address)":{"notice":"Completes bridge transaction on origin chain by claiming originally deposited capital"},"dispute(bytes32)":{"notice":"Disputes an outstanding proof in case relayer provided dest chain tx is invalid"},"getBridgeTransaction(bytes)":{"notice":"Decodes bridge request into a bridge transaction"},"protocolFeeRate()":{"notice":"Protocol fee rate taken on origin amount deposited in origin chain"},"protocolFees(address)":{"notice":"Protocol fee amounts accumulated"},"prove(bytes,bytes32)":{"notice":"Provides proof on origin side that relayer provided funds on destination side of bridge transaction"},"refund(bytes)":{"notice":"Refunds an outstanding bridge transaction in case optimistic bridging failed"},"relay(bytes)":{"notice":"Relays destination side of bridge transaction by off-chain relayer"}},"version":1},"developerDoc":{"errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}],"AddressEmptyCode(address)":[{"details":"There's no code at `target` (it is not a contract)."}],"AddressInsufficientBalance(address)":[{"details":"The ETH balance of the account is not enough to perform the operation."}],"FailedInnerCall()":[{"details":"A call to an address target failed. The target may have reverted."}],"SafeERC20FailedOperation(address)":[{"details":"An operation with an ERC-20 token failed."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"params":{"params":"The parameters required to bridge"}},"canClaim(bytes32,address)":{"params":{"relayer":"The address of the relayer attempting to claim","transactionId":"The transaction id associated with the encoded bridge transaction to check"}},"claim(bytes,address)":{"params":{"request":"The encoded bridge transaction to claim on origin chain","to":"The recipient address of the funds"}},"dispute(bytes32)":{"params":{"transactionId":"The transaction id associated with the encoded bridge transaction to dispute"}},"getBridgeTransaction(bytes)":{"params":{"request":"The bridge request to decode"}},"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"prove(bytes,bytes32)":{"params":{"destTxHash":"The destination tx hash proving bridge transaction was relayed","request":"The encoded bridge transaction to prove on origin chain"}},"refund(bytes)":{"params":{"request":"The encoded bridge transaction to refund"}},"relay(bytes)":{"params":{"request":"The encoded bridge transaction to relay on destination chain"}},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"stateVariables":{"nonce":{"details":"to prevent replays"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineNotExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineTooShort\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputePeriodNotPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputePeriodPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MsgValueIncorrect\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SenderIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StatusIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenNotContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransactionRelayed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositRefunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"BridgeProofDisputed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"transactionHash\",\"type\":\"bytes32\"}],\"name\":\"BridgeProofProvided\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"BridgeRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"}],\"name\":\"BridgeRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DISPUTE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_DEADLINE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROVE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"addGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"addGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"addRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"bridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeProofs\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"timestamp\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeRelays\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeStatuses\",\"outputs\":[{\"internalType\":\"enum FastBridge.BridgeStatus\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"canClaim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"dispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"getBridgeTransaction\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originSender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destRecipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originFeeAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeTransaction\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"destTxHash\",\"type\":\"bytes32\"}],\"name\":\"prove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"refund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"removeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"removeGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"removeRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}],\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"AddressInsufficientBalance(address)\":[{\"details\":\"The ETH balance of the account is not enough to perform the operation.\"}],\"FailedInnerCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"params\":{\"params\":\"The parameters required to bridge\"}},\"canClaim(bytes32,address)\":{\"params\":{\"relayer\":\"The address of the relayer attempting to claim\",\"transactionId\":\"The transaction id associated with the encoded bridge transaction to check\"}},\"claim(bytes,address)\":{\"params\":{\"request\":\"The encoded bridge transaction to claim on origin chain\",\"to\":\"The recipient address of the funds\"}},\"dispute(bytes32)\":{\"params\":{\"transactionId\":\"The transaction id associated with the encoded bridge transaction to dispute\"}},\"getBridgeTransaction(bytes)\":{\"params\":{\"request\":\"The bridge request to decode\"}},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"prove(bytes,bytes32)\":{\"params\":{\"destTxHash\":\"The destination tx hash proving bridge transaction was relayed\",\"request\":\"The encoded bridge transaction to prove on origin chain\"}},\"refund(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to refund\"}},\"relay(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to relay on destination chain\"}},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"stateVariables\":{\"nonce\":{\"details\":\"to prevent replays\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DISPUTE_PERIOD()\":{\"notice\":\"Dispute period for relayed transactions\"},\"MIN_DEADLINE_PERIOD()\":{\"notice\":\"Minimum deadline period to relay a requested bridge transaction\"},\"PROVE_PERIOD()\":{\"notice\":\"Prove period added to deadline period for proven transactions\"},\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"notice\":\"Initiates bridge on origin chain to be relayed by off-chain relayer\"},\"bridgeProofs(bytes32)\":{\"notice\":\"Proof of relayed bridge tx on origin chain\"},\"bridgeRelays(bytes32)\":{\"notice\":\"Whether bridge has been relayed on destination chain\"},\"bridgeStatuses(bytes32)\":{\"notice\":\"Status of the bridge tx on origin chain\"},\"canClaim(bytes32,address)\":{\"notice\":\"Checks if the dispute period has passed so bridge deposit can be claimed\"},\"chainGasAmount()\":{\"notice\":\"Chain gas amount to forward as rebate if requested\"},\"claim(bytes,address)\":{\"notice\":\"Completes bridge transaction on origin chain by claiming originally deposited capital\"},\"dispute(bytes32)\":{\"notice\":\"Disputes an outstanding proof in case relayer provided dest chain tx is invalid\"},\"getBridgeTransaction(bytes)\":{\"notice\":\"Decodes bridge request into a bridge transaction\"},\"protocolFeeRate()\":{\"notice\":\"Protocol fee rate taken on origin amount deposited in origin chain\"},\"protocolFees(address)\":{\"notice\":\"Protocol fee amounts accumulated\"},\"prove(bytes,bytes32)\":{\"notice\":\"Provides proof on origin side that relayer provided funds on destination side of bridge transaction\"},\"refund(bytes)\":{\"notice\":\"Refunds an outstanding bridge transaction in case optimistic bridging failed\"},\"relay(bytes)\":{\"notice\":\"Relays destination side of bridge transaction by off-chain relayer\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"FastBridge\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0xfdd0a71cdd1fe45137a59bc8e7544699eb71ead398af2fd0f1cf448a878ccacd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://07ce767dbb21de80ca0b546310d3c374ed7ddcf5376c7085f15c7812f7678819\",\"dweb:/ipfs/QmQ3JUoivC7YRSxZnRstRKmJJ8x8cLLhEbgWsiXV5NmYrs\"]}},\"version\":1}"},"hashes":{"DEFAULT_ADMIN_ROLE()":"a217fddf","DISPUTE_PERIOD()":"a5bbe22b","FEE_BPS()":"bf333f2c","FEE_RATE_MAX()":"0f5f6ed7","GOVERNOR_ROLE()":"ccc57490","GUARD_ROLE()":"03ed0ee5","MIN_DEADLINE_PERIOD()":"820688d5","PROVE_PERIOD()":"d3cbc760","RELAYER_ROLE()":"926d7d7f","addGovernor(address)":"3c4a25d0","addGuard(address)":"6913a63c","addRelayer(address)":"dd39f00d","bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":"45851694","bridgeProofs(bytes32)":"91ad5039","bridgeRelays(bytes32)":"8379a24f","bridgeStatuses(bytes32)":"051287bc","canClaim(bytes32,address)":"aa9641ab","chainGasAmount()":"e00a83e0","claim(bytes,address)":"41fcb612","deployBlock()":"a3ec191a","dispute(bytes32)":"add98c70","getBridgeTransaction(bytes)":"ac11fb1a","getRoleAdmin(bytes32)":"248a9ca3","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","nonce()":"affed0e0","protocolFeeRate()":"58f85880","protocolFees(address)":"dcf844a7","prove(bytes,bytes32)":"886d36ff","refund(bytes)":"5eb7d946","relay(bytes)":"8f0d6f17","removeGovernor(address)":"eecdac88","removeGuard(address)":"b6235016","removeRelayer(address)":"60f0a5ac","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","setChainGasAmount(uint256)":"b250fe6b","setProtocolFeeRate(uint256)":"b13aa2d6","supportsInterface(bytes4)":"01ffc9a7","sweepProtocolFees(address,address)":"06f333f2"}},"solidity/FastBridgeMock.sol:FastBridgeMock":{"code":"0x60a06040523480156200001157600080fd5b50604051620027a7380380620027a78339810160408190526200003491620000fe565b80620000426000826200004f565b5050436080525062000130565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16620000f4576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620000ab3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001620000f8565b5060005b92915050565b6000602082840312156200011157600080fd5b81516001600160a01b03811681146200012957600080fd5b9392505050565b60805161265b6200014c600039600061056a015261265b6000f3fe6080604052600436106102855760003560e01c8063a217fddf11610153578063b250fe6b116100cb578063d547741f1161007f578063dd39f00d11610064578063dd39f00d14610762578063e00a83e014610782578063eecdac881461079857600080fd5b8063d547741f14610715578063dcf844a71461073557600080fd5b8063bf333f2c116100b0578063bf333f2c146106aa578063c72870cc146106c1578063ccc57490146106e157600080fd5b8063b250fe6b1461066a578063b62350161461068a57600080fd5b8063acaebbf111610122578063aedf009d11610107578063aedf009d14610614578063affed0e014610634578063b13aa2d61461064a57600080fd5b8063acaebbf1146105d9578063add98c70146105f957600080fd5b8063a217fddf14610543578063a3ec191a14610558578063aa9641ab1461058c578063ac11fb1a146105ac57600080fd5b8063458516941161020157806385ad903d116101b55780638f0d6f171161019a5780638f0d6f17146104b057806391d14854146104be578063926d7d7f1461050f57600080fd5b806385ad903d14610468578063886d36ff1461049557600080fd5b80635eb7d946116101e65780635eb7d9461461040d57806360f0a5ac146104285780636913a63c1461044857600080fd5b806345851694146103e957806358f85880146103f757600080fd5b8063248a9ca31161025857806336568abe1161023d57806336568abe146103895780633c4a25d0146103a957806341fcb612146103c957600080fd5b8063248a9ca3146103395780632f2ff15d1461036957600080fd5b806301ffc9a71461028a57806303ed0ee5146102bf57806306f333f2146103015780630f5f6ed714610323575b600080fd5b34801561029657600080fd5b506102aa6102a5366004611cc5565b6107b8565b60405190151581526020015b60405180910390f35b3480156102cb57600080fd5b506102f37f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b6040519081526020016102b6565b34801561030d57600080fd5b5061032161031c366004611d39565b610851565b005b34801561032f57600080fd5b506102f361271081565b34801561034557600080fd5b506102f3610354366004611d72565b60009081526020819052604090206001015490565b34801561037557600080fd5b50610321610384366004611d8b565b6109b0565b34801561039557600080fd5b506103216103a4366004611d8b565b6109db565b3480156103b557600080fd5b506103216103c4366004611db0565b610a39565b3480156103d557600080fd5b506103216103e4366004611ef5565b610aec565b6103216103e4366004612015565b34801561040357600080fd5b506102f360015481565b34801561041957600080fd5b506103216103e4366004612032565b34801561043457600080fd5b50610321610443366004611db0565b610b4e565b34801561045457600080fd5b50610321610463366004611db0565b610bfa565b34801561047457600080fd5b5061048861048336600461206f565b610ca6565b6040516102b691906120fe565b3480156104a157600080fd5b506103216103e4366004612111565b6103216103e4366004612032565b3480156104ca57600080fd5b506102aa6104d9366004611d8b565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561051b57600080fd5b506102f37fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b34801561054f57600080fd5b506102f3600081565b34801561056457600080fd5b506102f37f000000000000000000000000000000000000000000000000000000000000000081565b34801561059857600080fd5b506102aa6105a7366004611d8b565b610e56565b3480156105b857600080fd5b506105cc6105c7366004612032565b610ebb565b6040516102b69190612156565b3480156105e557600080fd5b506103216105f4366004612270565b610f2e565b34801561060557600080fd5b506103216103e4366004611d72565b34801561062057600080fd5b5061032161062f3660046122b0565b6110fe565b34801561064057600080fd5b506102f360045481565b34801561065657600080fd5b50610321610665366004611d72565b611189565b34801561067657600080fd5b50610321610685366004611d72565b6112d3565b34801561069657600080fd5b506103216106a5366004611db0565b6113a9565b3480156106b657600080fd5b506102f3620f424081565b3480156106cd57600080fd5b506103216106dc366004612309565b611455565b3480156106ed57600080fd5b506102f37f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b34801561072157600080fd5b50610321610730366004611d8b565b6114db565b34801561074157600080fd5b506102f3610750366004611db0565b60026020526000908152604090205481565b34801561076e57600080fd5b5061032161077d366004611db0565b611500565b34801561078e57600080fd5b506102f360035481565b3480156107a457600080fd5b506103216107b3366004611db0565b6115ac565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061084b57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff166108ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600260205260408120549081900361092157505050565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260026020526040812055610952908383611658565b6040805173ffffffffffffffffffffffffffffffffffffffff8086168252841660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b5050565b6000828152602081905260409020600101546109cb816117af565b6109d583836117bc565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610a2a576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a3482826118b8565b505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610a7457600080fd5b610a9e7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55826117bc565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5906020015b60405180910390a150565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6e6f7420696d706c656d656e746564000000000000000000000000000000000060448201526064016108e5565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610b8957600080fd5b610bb37fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4826118b8565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b90602001610ae1565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610c3557600080fd5b610c5f7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d826117bc565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f5990602001610ae1565b6060816004811115610cba57610cba6123a1565b600003610cfa57505060408051808201909152600481527f4e554c4c00000000000000000000000000000000000000000000000000000000602082015290565b816004811115610d0c57610d0c6123a1565b600103610d4c57505060408051808201909152600981527f5245515545535445440000000000000000000000000000000000000000000000602082015290565b816004811115610d5e57610d5e6123a1565b600203610d9e57505060408051808201909152600e81527f52454c415945525f50524f564544000000000000000000000000000000000000602082015290565b816004811115610db057610db06123a1565b600303610df057505060408051808201909152600f81527f52454c415945525f434c41494d45440000000000000000000000000000000000602082015290565b816004811115610e0257610e026123a1565b600403610e4257505060408051808201909152600881527f524546554e444544000000000000000000000000000000000000000000000000602082015290565b505060408051602081019091526000815290565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6e6f7420696d706c656d656e746564000000000000000000000000000000000060448201526000906064016108e5565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201528251909161084b91840181019084016123f1565b6000620f42406001548360a00151610f4691906124ec565b610f509190612503565b9050808260a001818151610f64919061253e565b9150818152505060006040518061018001604052804663ffffffff168152602001846000015163ffffffff168152602001846020015173ffffffffffffffffffffffffffffffffffffffff168152602001846040015173ffffffffffffffffffffffffffffffffffffffff168152602001846060015173ffffffffffffffffffffffffffffffffffffffff168152602001846080015173ffffffffffffffffffffffffffffffffffffffff1681526020018460a0015181526020018460c0015181526020018381526020018460e001511515815260200184610100015181526020016004600081548092919061105990612551565b90915550905260405161106f9190602001612156565b6040516020818303038152906040529050826020015173ffffffffffffffffffffffffffffffffffffffff16857f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a838660000151876060015188608001518960a001518a60c001518b60e001516040516110ef9796959493929190612589565b60405180910390a35050505050565b600061110982610ebb565b9050806040015173ffffffffffffffffffffffffffffffffffffffff16847f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a84846020015185608001518660a001518760c001518860e0015189610120015160405161117b9796959493929190612589565b60405180910390a350505050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16611221576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064016108e5565b61271081111561128d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064016108e5565b600180549082905560408051828152602081018490527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a15050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff1661136b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064016108e5565b600380549082905560408051828152602081018490527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa91016112c7565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166113e457600080fd5b61140e7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d826118b8565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d04890602001610ae1565b6040805163ffffffff8816815273ffffffffffffffffffffffffffffffffffffffff878116602083015286811682840152606082018690526080820185905260a082018490529151898316928b16918c917ff8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c9181900360c00190a4505050505050505050565b6000828152602081905260409020600101546114f6816117af565b6109d583836118b8565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661153b57600080fd5b6115657fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4826117bc565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c590602001610ae1565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166115e757600080fd5b6116117f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55826118b8565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b90602001610ae1565b3073ffffffffffffffffffffffffffffffffffffffff83160361167a57505050565b8060000361168757505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff84160161178e5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461171e576040519150601f19603f3d011682016040523d82523d6000602084013e611723565b606091505b50509050806109d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c65640000000000000000000000000060448201526064016108e5565b610a3473ffffffffffffffffffffffffffffffffffffffff84168383611973565b6117b98133611a00565b50565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff166118b05760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561184e3390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161084b565b50600061084b565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16156118b05760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161084b565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a34908490611a86565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109ac576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602481018390526044016108e5565b6000611aa873ffffffffffffffffffffffffffffffffffffffff841683611b1c565b90508051600014158015611acd575080806020019051810190611acb91906125ec565b155b15610a34576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016108e5565b6060611b2a83836000611b31565b9392505050565b606081471015611b6f576040517fcd7860590000000000000000000000000000000000000000000000000000000081523060048201526024016108e5565b6000808573ffffffffffffffffffffffffffffffffffffffff168486604051611b989190612609565b60006040518083038185875af1925050503d8060008114611bd5576040519150601f19603f3d011682016040523d82523d6000602084013e611bda565b606091505b5091509150611bea868383611bf4565b9695505050505050565b606082611c0957611c0482611c83565b611b2a565b8151158015611c2d575073ffffffffffffffffffffffffffffffffffffffff84163b155b15611c7c576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016108e5565b5080611b2a565b805115611c935780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060208284031215611cd757600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611b2a57600080fd5b73ffffffffffffffffffffffffffffffffffffffff811681146117b957600080fd5b8035611d3481611d07565b919050565b60008060408385031215611d4c57600080fd5b8235611d5781611d07565b91506020830135611d6781611d07565b809150509250929050565b600060208284031215611d8457600080fd5b5035919050565b60008060408385031215611d9e57600080fd5b823591506020830135611d6781611d07565b600060208284031215611dc257600080fd5b8135611b2a81611d07565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715611e2057611e20611dcd565b60405290565b604051610180810167ffffffffffffffff81118282101715611e2057611e20611dcd565b600082601f830112611e5b57600080fd5b813567ffffffffffffffff80821115611e7657611e76611dcd565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611ebc57611ebc611dcd565b81604052838152866020858801011115611ed557600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215611f0857600080fd5b823567ffffffffffffffff811115611f1f57600080fd5b611f2b85828601611e4a565b9250506020830135611d6781611d07565b63ffffffff811681146117b957600080fd5b8035611d3481611f3c565b80151581146117b957600080fd5b8035611d3481611f59565b60006101208284031215611f8557600080fd5b611f8d611dfc565b9050611f9882611f4e565b8152611fa660208301611d29565b6020820152611fb760408301611d29565b6040820152611fc860608301611d29565b6060820152611fd960808301611d29565b608082015260a082013560a082015260c082013560c0820152611ffe60e08301611f67565b60e082015261010080830135818301525092915050565b6000610120828403121561202857600080fd5b611b2a8383611f72565b60006020828403121561204457600080fd5b813567ffffffffffffffff81111561205b57600080fd5b61206784828501611e4a565b949350505050565b60006020828403121561208157600080fd5b813560058110611b2a57600080fd5b60005b838110156120ab578181015183820152602001612093565b50506000910152565b600081518084526120cc816020860160208601612090565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611b2a60208301846120b4565b6000806040838503121561212457600080fd5b823567ffffffffffffffff81111561213b57600080fd5b61214785828601611e4a565b95602094909401359450505050565b815163ffffffff1681526101808101602083015161217c602084018263ffffffff169052565b5060408301516121a4604084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060608301516121cc606084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060808301516121f4608084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060a083015161221c60a084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c083015160c083015260e083015160e0830152610100808401518184015250610120808401516122518285018215159052565b5050610140838101519083015261016092830151929091019190915290565b6000806000610160848603121561228657600080fd5b83359250602084013561229881611d07565b91506122a78560408601611f72565b90509250925092565b6000806000606084860312156122c557600080fd5b8335925060208401356122d781611d07565b9150604084013567ffffffffffffffff8111156122f357600080fd5b6122ff86828701611e4a565b9150509250925092565b60008060008060008060008060006101208a8c03121561232857600080fd5b8935985060208a013561233a81611d07565b975060408a013561234a81611d07565b965060608a013561235a81611f3c565b955060808a013561236a81611d07565b945060a08a013561237a81611d07565b8094505060c08a0135925060e08a013591506101008a013590509295985092959850929598565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8051611d3481611f3c565b8051611d3481611d07565b8051611d3481611f59565b6000610180828403121561240457600080fd5b61240c611e26565b612415836123d0565b8152612423602084016123d0565b6020820152612434604084016123db565b6040820152612445606084016123db565b6060820152612456608084016123db565b608082015261246760a084016123db565b60a082015260c083015160c082015260e083015160e082015261010080840151818301525061012061249a8185016123e6565b908201526101408381015190820152610160928301519281019290925250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761084b5761084b6124bd565b600082612539577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561084b5761084b6124bd565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612582576125826124bd565b5060010190565b60e08152600061259c60e083018a6120b4565b63ffffffff9890981660208301525073ffffffffffffffffffffffffffffffffffffffff9586166040820152939094166060840152608083019190915260a082015290151560c090910152919050565b6000602082840312156125fe57600080fd5b8151611b2a81611f59565b6000825161261b818460208701612090565b919091019291505056fea26469706673582212202542a86ea1af268a7f612e2c83128fb706733cc2fea925df68bbd0f008d32b6a64736f6c63430008140033","runtime-code":"0x6080604052600436106102855760003560e01c8063a217fddf11610153578063b250fe6b116100cb578063d547741f1161007f578063dd39f00d11610064578063dd39f00d14610762578063e00a83e014610782578063eecdac881461079857600080fd5b8063d547741f14610715578063dcf844a71461073557600080fd5b8063bf333f2c116100b0578063bf333f2c146106aa578063c72870cc146106c1578063ccc57490146106e157600080fd5b8063b250fe6b1461066a578063b62350161461068a57600080fd5b8063acaebbf111610122578063aedf009d11610107578063aedf009d14610614578063affed0e014610634578063b13aa2d61461064a57600080fd5b8063acaebbf1146105d9578063add98c70146105f957600080fd5b8063a217fddf14610543578063a3ec191a14610558578063aa9641ab1461058c578063ac11fb1a146105ac57600080fd5b8063458516941161020157806385ad903d116101b55780638f0d6f171161019a5780638f0d6f17146104b057806391d14854146104be578063926d7d7f1461050f57600080fd5b806385ad903d14610468578063886d36ff1461049557600080fd5b80635eb7d946116101e65780635eb7d9461461040d57806360f0a5ac146104285780636913a63c1461044857600080fd5b806345851694146103e957806358f85880146103f757600080fd5b8063248a9ca31161025857806336568abe1161023d57806336568abe146103895780633c4a25d0146103a957806341fcb612146103c957600080fd5b8063248a9ca3146103395780632f2ff15d1461036957600080fd5b806301ffc9a71461028a57806303ed0ee5146102bf57806306f333f2146103015780630f5f6ed714610323575b600080fd5b34801561029657600080fd5b506102aa6102a5366004611cc5565b6107b8565b60405190151581526020015b60405180910390f35b3480156102cb57600080fd5b506102f37f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b6040519081526020016102b6565b34801561030d57600080fd5b5061032161031c366004611d39565b610851565b005b34801561032f57600080fd5b506102f361271081565b34801561034557600080fd5b506102f3610354366004611d72565b60009081526020819052604090206001015490565b34801561037557600080fd5b50610321610384366004611d8b565b6109b0565b34801561039557600080fd5b506103216103a4366004611d8b565b6109db565b3480156103b557600080fd5b506103216103c4366004611db0565b610a39565b3480156103d557600080fd5b506103216103e4366004611ef5565b610aec565b6103216103e4366004612015565b34801561040357600080fd5b506102f360015481565b34801561041957600080fd5b506103216103e4366004612032565b34801561043457600080fd5b50610321610443366004611db0565b610b4e565b34801561045457600080fd5b50610321610463366004611db0565b610bfa565b34801561047457600080fd5b5061048861048336600461206f565b610ca6565b6040516102b691906120fe565b3480156104a157600080fd5b506103216103e4366004612111565b6103216103e4366004612032565b3480156104ca57600080fd5b506102aa6104d9366004611d8b565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561051b57600080fd5b506102f37fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b34801561054f57600080fd5b506102f3600081565b34801561056457600080fd5b506102f37f000000000000000000000000000000000000000000000000000000000000000081565b34801561059857600080fd5b506102aa6105a7366004611d8b565b610e56565b3480156105b857600080fd5b506105cc6105c7366004612032565b610ebb565b6040516102b69190612156565b3480156105e557600080fd5b506103216105f4366004612270565b610f2e565b34801561060557600080fd5b506103216103e4366004611d72565b34801561062057600080fd5b5061032161062f3660046122b0565b6110fe565b34801561064057600080fd5b506102f360045481565b34801561065657600080fd5b50610321610665366004611d72565b611189565b34801561067657600080fd5b50610321610685366004611d72565b6112d3565b34801561069657600080fd5b506103216106a5366004611db0565b6113a9565b3480156106b657600080fd5b506102f3620f424081565b3480156106cd57600080fd5b506103216106dc366004612309565b611455565b3480156106ed57600080fd5b506102f37f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b34801561072157600080fd5b50610321610730366004611d8b565b6114db565b34801561074157600080fd5b506102f3610750366004611db0565b60026020526000908152604090205481565b34801561076e57600080fd5b5061032161077d366004611db0565b611500565b34801561078e57600080fd5b506102f360035481565b3480156107a457600080fd5b506103216107b3366004611db0565b6115ac565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061084b57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff166108ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600260205260408120549081900361092157505050565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260026020526040812055610952908383611658565b6040805173ffffffffffffffffffffffffffffffffffffffff8086168252841660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b5050565b6000828152602081905260409020600101546109cb816117af565b6109d583836117bc565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610a2a576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a3482826118b8565b505050565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610a7457600080fd5b610a9e7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55826117bc565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5906020015b60405180910390a150565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6e6f7420696d706c656d656e746564000000000000000000000000000000000060448201526064016108e5565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610b8957600080fd5b610bb37fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4826118b8565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b90602001610ae1565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff16610c3557600080fd5b610c5f7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d826117bc565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f5990602001610ae1565b6060816004811115610cba57610cba6123a1565b600003610cfa57505060408051808201909152600481527f4e554c4c00000000000000000000000000000000000000000000000000000000602082015290565b816004811115610d0c57610d0c6123a1565b600103610d4c57505060408051808201909152600981527f5245515545535445440000000000000000000000000000000000000000000000602082015290565b816004811115610d5e57610d5e6123a1565b600203610d9e57505060408051808201909152600e81527f52454c415945525f50524f564544000000000000000000000000000000000000602082015290565b816004811115610db057610db06123a1565b600303610df057505060408051808201909152600f81527f52454c415945525f434c41494d45440000000000000000000000000000000000602082015290565b816004811115610e0257610e026123a1565b600403610e4257505060408051808201909152600881527f524546554e444544000000000000000000000000000000000000000000000000602082015290565b505060408051602081019091526000815290565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6e6f7420696d706c656d656e746564000000000000000000000000000000000060448201526000906064016108e5565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201528251909161084b91840181019084016123f1565b6000620f42406001548360a00151610f4691906124ec565b610f509190612503565b9050808260a001818151610f64919061253e565b9150818152505060006040518061018001604052804663ffffffff168152602001846000015163ffffffff168152602001846020015173ffffffffffffffffffffffffffffffffffffffff168152602001846040015173ffffffffffffffffffffffffffffffffffffffff168152602001846060015173ffffffffffffffffffffffffffffffffffffffff168152602001846080015173ffffffffffffffffffffffffffffffffffffffff1681526020018460a0015181526020018460c0015181526020018381526020018460e001511515815260200184610100015181526020016004600081548092919061105990612551565b90915550905260405161106f9190602001612156565b6040516020818303038152906040529050826020015173ffffffffffffffffffffffffffffffffffffffff16857f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a838660000151876060015188608001518960a001518a60c001518b60e001516040516110ef9796959493929190612589565b60405180910390a35050505050565b600061110982610ebb565b9050806040015173ffffffffffffffffffffffffffffffffffffffff16847f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a84846020015185608001518660a001518760c001518860e0015189610120015160405161117b9796959493929190612589565b60405180910390a350505050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff16611221576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064016108e5565b61271081111561128d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064016108e5565b600180549082905560408051828152602081018490527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a15050565b3360009081527f6f3b488caa0dc03e5f3d9fd6a25fa8755afcfd62ccffb6e436c696bfa6b866de602052604090205460ff1661136b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616c6c6572206973206e6f74206120676f7665726e6f72000000000000000060448201526064016108e5565b600380549082905560408051828152602081018490527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa91016112c7565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166113e457600080fd5b61140e7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d826118b8565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d04890602001610ae1565b6040805163ffffffff8816815273ffffffffffffffffffffffffffffffffffffffff878116602083015286811682840152606082018690526080820185905260a082018490529151898316928b16918c917ff8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c9181900360c00190a4505050505050505050565b6000828152602081905260409020600101546114f6816117af565b6109d583836118b8565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1661153b57600080fd5b6115657fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4826117bc565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c590602001610ae1565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff166115e757600080fd5b6116117f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55826118b8565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b90602001610ae1565b3073ffffffffffffffffffffffffffffffffffffffff83160361167a57505050565b8060000361168757505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff84160161178e5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461171e576040519150601f19603f3d011682016040523d82523d6000602084013e611723565b606091505b50509050806109d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c65640000000000000000000000000060448201526064016108e5565b610a3473ffffffffffffffffffffffffffffffffffffffff84168383611973565b6117b98133611a00565b50565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff166118b05760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561184e3390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161084b565b50600061084b565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16156118b05760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161084b565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a34908490611a86565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109ac576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602481018390526044016108e5565b6000611aa873ffffffffffffffffffffffffffffffffffffffff841683611b1c565b90508051600014158015611acd575080806020019051810190611acb91906125ec565b155b15610a34576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016108e5565b6060611b2a83836000611b31565b9392505050565b606081471015611b6f576040517fcd7860590000000000000000000000000000000000000000000000000000000081523060048201526024016108e5565b6000808573ffffffffffffffffffffffffffffffffffffffff168486604051611b989190612609565b60006040518083038185875af1925050503d8060008114611bd5576040519150601f19603f3d011682016040523d82523d6000602084013e611bda565b606091505b5091509150611bea868383611bf4565b9695505050505050565b606082611c0957611c0482611c83565b611b2a565b8151158015611c2d575073ffffffffffffffffffffffffffffffffffffffff84163b155b15611c7c576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016108e5565b5080611b2a565b805115611c935780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060208284031215611cd757600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611b2a57600080fd5b73ffffffffffffffffffffffffffffffffffffffff811681146117b957600080fd5b8035611d3481611d07565b919050565b60008060408385031215611d4c57600080fd5b8235611d5781611d07565b91506020830135611d6781611d07565b809150509250929050565b600060208284031215611d8457600080fd5b5035919050565b60008060408385031215611d9e57600080fd5b823591506020830135611d6781611d07565b600060208284031215611dc257600080fd5b8135611b2a81611d07565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715611e2057611e20611dcd565b60405290565b604051610180810167ffffffffffffffff81118282101715611e2057611e20611dcd565b600082601f830112611e5b57600080fd5b813567ffffffffffffffff80821115611e7657611e76611dcd565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611ebc57611ebc611dcd565b81604052838152866020858801011115611ed557600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215611f0857600080fd5b823567ffffffffffffffff811115611f1f57600080fd5b611f2b85828601611e4a565b9250506020830135611d6781611d07565b63ffffffff811681146117b957600080fd5b8035611d3481611f3c565b80151581146117b957600080fd5b8035611d3481611f59565b60006101208284031215611f8557600080fd5b611f8d611dfc565b9050611f9882611f4e565b8152611fa660208301611d29565b6020820152611fb760408301611d29565b6040820152611fc860608301611d29565b6060820152611fd960808301611d29565b608082015260a082013560a082015260c082013560c0820152611ffe60e08301611f67565b60e082015261010080830135818301525092915050565b6000610120828403121561202857600080fd5b611b2a8383611f72565b60006020828403121561204457600080fd5b813567ffffffffffffffff81111561205b57600080fd5b61206784828501611e4a565b949350505050565b60006020828403121561208157600080fd5b813560058110611b2a57600080fd5b60005b838110156120ab578181015183820152602001612093565b50506000910152565b600081518084526120cc816020860160208601612090565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611b2a60208301846120b4565b6000806040838503121561212457600080fd5b823567ffffffffffffffff81111561213b57600080fd5b61214785828601611e4a565b95602094909401359450505050565b815163ffffffff1681526101808101602083015161217c602084018263ffffffff169052565b5060408301516121a4604084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060608301516121cc606084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060808301516121f4608084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060a083015161221c60a084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c083015160c083015260e083015160e0830152610100808401518184015250610120808401516122518285018215159052565b5050610140838101519083015261016092830151929091019190915290565b6000806000610160848603121561228657600080fd5b83359250602084013561229881611d07565b91506122a78560408601611f72565b90509250925092565b6000806000606084860312156122c557600080fd5b8335925060208401356122d781611d07565b9150604084013567ffffffffffffffff8111156122f357600080fd5b6122ff86828701611e4a565b9150509250925092565b60008060008060008060008060006101208a8c03121561232857600080fd5b8935985060208a013561233a81611d07565b975060408a013561234a81611d07565b965060608a013561235a81611f3c565b955060808a013561236a81611d07565b945060a08a013561237a81611d07565b8094505060c08a0135925060e08a013591506101008a013590509295985092959850929598565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8051611d3481611f3c565b8051611d3481611d07565b8051611d3481611f59565b6000610180828403121561240457600080fd5b61240c611e26565b612415836123d0565b8152612423602084016123d0565b6020820152612434604084016123db565b6040820152612445606084016123db565b6060820152612456608084016123db565b608082015261246760a084016123db565b60a082015260c083015160c082015260e083015160e082015261010080840151818301525061012061249a8185016123e6565b908201526101408381015190820152610160928301519281019290925250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761084b5761084b6124bd565b600082612539577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561084b5761084b6124bd565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612582576125826124bd565b5060010190565b60e08152600061259c60e083018a6120b4565b63ffffffff9890981660208301525073ffffffffffffffffffffffffffffffffffffffff9586166040820152939094166060840152608083019190915260a082015290151560c090910152919050565b6000602082840312156125fe57600080fd5b8151611b2a81611f59565b6000825161261b818460208701612090565b919091019291505056fea26469706673582212202542a86ea1af268a7f612e2c83128fb706733cc2fea925df68bbd0f008d32b6a64736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n ) external {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"54750:4347:0:-:0;;;54896:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;54930:6;41292:38;32700:4;54930:6;41292:10;:38::i;:::-;-1:-1:-1;;54962:12:0::1;54948:26;::::0;-1:-1:-1;54750:4347:0;;36647:316;36724:4;33422:12;;;;;;;;;;;-1:-1:-1;;;;;33422:29:0;;;;;;;;;;;;36740:217;;36783:6;:12;;;;;;;;;;;-1:-1:-1;;;;;36783:29:0;;;;;;;;;:36;;-1:-1:-1;;36783:36:0;36815:4;36783:36;;;36865:12;22980:10;;22901:96;36865:12;-1:-1:-1;;;;;36838:40:0;36856:7;-1:-1:-1;;;;;36838:40:0;36850:4;36838:40;;;;;;;;;;-1:-1:-1;36899:4:0;36892:11;;36740:217;-1:-1:-1;36941:5:0;36740:217;36647:316;;;;:::o;14:290:1:-;84:6;137:2;125:9;116:7;112:23;108:32;105:52;;;153:1;150;143:12;105:52;179:16;;-1:-1:-1;;;;;224:31:1;;214:42;;204:70;;270:1;267;260:12;204:70;293:5;14:290;-1:-1:-1;;;14:290:1:o;:::-;54750:4347:0;;;;;;;;;;;;","srcMapRuntime":"54750:4347:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33033:202;;;;;;;;;;-1:-1:-1;33033:202:0;;;;;:::i;:::-;;:::i;:::-;;;612:14:1;;605:22;587:41;;575:2;560:18;33033:202:0;;;;;;;;40292:60;;;;;;;;;;;;40329:23;40292:60;;;;;785:25:1;;;773:2;758:18;40292:60:0;639:177:1;42828:348:0;;;;;;;;;;-1:-1:-1;42828:348:0;;;;;:::i;:::-;;:::i;:::-;;40474:45;;;;;;;;;;;;40513:6;40474:45;;34278:120;;;;;;;;;;-1:-1:-1;34278:120:0;;;;;:::i;:::-;34343:7;34369:12;;;;;;;;;;:22;;;;34278:120;34694:136;;;;;;;;;;-1:-1:-1;34694:136:0;;;;;:::i;:::-;;:::i;35796:245::-;;;;;;;;;;-1:-1:-1;35796:245:0;;;;;:::i;:::-;;:::i;42127:199::-;;;;;;;;;;-1:-1:-1;42127:199:0;;;;;:::i;:::-;;:::i;58803:100::-;;;;;;;;;;-1:-1:-1;58803:100:0;;;;;:::i;:::-;;:::i;58343:103::-;;;;;;:::i;40636:30::-;;;;;;;;;;;;;;;;59006:89;;;;;;;;;;-1:-1:-1;59006:89:0;;;;;:::i;41542:199::-;;;;;;;;;;-1:-1:-1;41542:199:0;;;;;:::i;:::-;;:::i;41747:181::-;;;;;;;;;;-1:-1:-1;41747:181:0;;;;;:::i;:::-;;:::i;55533:528::-;;;;;;;;;;-1:-1:-1;55533:528:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;58554:108::-;;;;;;;;;;-1:-1:-1;58554:108:0;;;;;:::i;58452:96::-;;;;;;:::i;33322:136::-;;;;;;;;;;-1:-1:-1;33322:136:0;;;;;:::i;:::-;33399:4;33422:12;;;;;;;;;;;:29;;;;;;;;;;;;;;;;33322:136;40222:64;;;;;;;;;;;;40261:25;40222:64;;32655:49;;;;;;;;;;-1:-1:-1;32655:49:0;32700:4;32655:49;;54853:36;;;;;;;;;;;;;;;58668:129;;;;;;;;;;-1:-1:-1;58668:129:0;;;;;:::i;:::-;;:::i;55046:163::-;;;;;;;;;;-1:-1:-1;55046:163:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;56067:1266::-;;;;;;;;;;-1:-1:-1;56067:1266:0;;;;;:::i;:::-;;:::i;58909:91::-;;;;;;;;;;-1:-1:-1;58909:91:0;;;;;:::i;57339:532::-;;;;;;;;;;-1:-1:-1;57339:532:0;;;;;:::i;:::-;;:::i;55019:20::-;;;;;;;;;;;;;;;;42543:279;;;;;;;;;;-1:-1:-1;42543:279:0;;;;;:::i;:::-;;:::i;43182:253::-;;;;;;;;;;-1:-1:-1;43182:253:0;;;;;:::i;:::-;;:::i;41934:187::-;;;;;;;;;;-1:-1:-1;41934:187:0;;;;;:::i;:::-;;:::i;40431:37::-;;;;;;;;;;;;40465:3;40431:37;;57877:460;;;;;;;;;;-1:-1:-1;57877:460:0;;;;;:::i;:::-;;:::i;40358:66::-;;;;;;;;;;;;40398:26;40358:66;;35110:138;;;;;;;;;;-1:-1:-1;35110:138:0;;;;;:::i;:::-;;:::i;40722:47::-;;;;;;;;;;-1:-1:-1;40722:47:0;;;;;:::i;:::-;;;;;;;;;;;;;;41343:193;;;;;;;;;;-1:-1:-1;41343:193:0;;;;;:::i;:::-;;:::i;40843:29::-;;;;;;;;;;;;;;;;42332:205;;;;;;;;;;-1:-1:-1;42332:205:0;;;;;:::i;:::-;;:::i;33033:202::-;33118:4;33141:47;;;33156:32;33141:47;;:87;;-1:-1:-1;24946:25:0;24931:40;;;;33192:36;33134:94;33033:202;-1:-1:-1;;33033:202:0:o;42828:348::-;41190:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41159:71;;;;;;;11835:2:1;41159:71:0;;;11817:21:1;11874:2;11854:18;;;11847:30;11913:26;11893:18;;;11886:54;11957:18;;41159:71:0;;;;;;;;;42941:19:::1;::::0;::::1;42921:17;42941:19:::0;;;:12:::1;:19;::::0;;;;;;42974:14;;;42970:27:::1;;42990:7;42828:348:::0;;:::o;42970:27::-:1;43038:19;::::0;::::1;43060:1;43038:19:::0;;;:12:::1;:19;::::0;;;;:23;43071:45:::1;::::0;43095:9;43106;43071:23:::1;:45::i;:::-;43131:38;::::0;;12198:42:1;12267:15;;;12249:34;;12319:15;;12314:2;12299:18;;12292:43;12351:18;;;12344:34;;;43131:38:0::1;::::0;12176:2:1;12161:18;43131:38:0::1;;;;;;;42911:265;41240:1;42828:348:::0;;:::o;34694:136::-;34343:7;34369:12;;;;;;;;;;:22;;;32932:16;32943:4;32932:10;:16::i;:::-;34798:25:::1;34809:4;34815:7;34798:10;:25::i;:::-;;34694:136:::0;;;:::o;35796:245::-;35889:34;;;22980:10;35889:34;35885:102;;35946:30;;;;;;;;;;;;;;35885:102;35997:37;36009:4;36015:18;35997:11;:37::i;:::-;;35796:245;;:::o;42127:199::-;42222:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;42186:48;;;;;;42244:36;40398:26;42270:9;42244:10;:36::i;:::-;-1:-1:-1;42295:24:0;;12565:42:1;12553:55;;12535:74;;42295:24:0;;12523:2:1;12508:18;42295:24:0;;;;;;;;42127:199;:::o;58803:100::-;58871:25;;;;;12822:2:1;58871:25:0;;;12804:21:1;12861:2;12841:18;;;12834:30;12900:17;12880:18;;;12873:45;12935:18;;58871:25:0;12620:339:1;41542:199:0;41638:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41602:48;;;;;;41660:35;40261:25;41686:8;41660:11;:35::i;:::-;-1:-1:-1;41710:24:0;;12565:42:1;12553:55;;12535:74;;41710:24:0;;12523:2:1;12508:18;41710:24:0;12389:226:1;41747:181:0;41836:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41800:48;;;;;;41858:30;40329:23;41881:6;41858:10;:30::i;:::-;-1:-1:-1;41903:18:0;;12565:42:1;12553:55;;12535:74;;41903:18:0;;12523:2:1;12508:18;41903::0;12389:226:1;55533:528:0;55615:13;55676:8;55644:40;;;;;;;;:::i;:::-;:28;:40;55640:59;;-1:-1:-1;;55686:13:0;;;;;;;;;;;;;;;;;;55533:528::o;55640:59::-;55750:8;55713:45;;;;;;;;:::i;:::-;:33;:45;55709:69;;-1:-1:-1;;55760:18:0;;;;;;;;;;;;;;;;;;55533:528::o;55709:69::-;55834:8;55792:50;;;;;;;;:::i;:::-;:38;:50;55788:79;;-1:-1:-1;;55844:23:0;;;;;;;;;;;;;;;;;;55533:528::o;55788:79::-;55924:8;55881:51;;;;;;;;:::i;:::-;:39;:51;55877:81;;-1:-1:-1;;55934:24:0;;;;;;;;;;;;;;;;;;55533:528::o;55877:81::-;56008:8;55972:44;;;;;;;;:::i;:::-;:32;:44;55968:67;;-1:-1:-1;;56018:17:0;;;;;;;;;;;;;;;;;;55533:528::o;55968:67::-;-1:-1:-1;;56045:9:0;;;;;;;;;-1:-1:-1;56045:9:0;;;55533:528::o;58668:129::-;58765:25;;;;;12822:2:1;58765:25:0;;;12804:21:1;12861:2;12841:18;;;12834:30;12900:17;12880:18;;;12873:45;58749:4:0;;12935:18:1;;58765:25:0;12620:339:1;55046:163:0;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55162:40:0;;-1:-1:-1;;55162:40:0;;;;;;;;;;:::i;56067:1266::-;56180:23;40465:3;56229:15;;56207:6;:19;;;:37;;;;:::i;:::-;56206:49;;;;:::i;:::-;56180:75;;56288:15;56265:6;:19;;:38;;;;;;;:::i;:::-;;;;;;;;56314:20;56361:649;;;;;;;;56419:13;56361:649;;;;;;56464:6;:17;;;56361:649;;;;;;56513:6;:13;;;56361:649;;;;;;56559:6;:9;;;56361:649;;;;;;56599:6;:18;;;56361:649;;;;;;56646:6;:16;;;56361:649;;;;;;56694:6;:19;;;56361:649;;;;56767:6;:17;;;56361:649;;;;56819:15;56361:649;;;;56866:6;:19;;;56361:649;;;;;;56913:6;:15;;;56361:649;;;;56953:5;;:7;;;;;;;;;:::i;:::-;;;;-1:-1:-1;56361:649:0;;56337:683;;;;;;;;:::i;:::-;;;;;;;;;;;;;56314:706;;57092:6;:13;;;57036:290;;57065:13;57036:290;57119:7;57140:6;:17;;;57171:6;:18;;;57203:6;:16;;;57233:6;:19;;;57266:6;:17;;;57297:6;:19;;;57036:290;;;;;;;;;;;;:::i;:::-;;;;;;;;56170:1163;;56067:1266;;;:::o;57339:532::-;57449:36;57488:29;57509:7;57488:20;:29::i;:::-;57449:68;;57588:11;:24;;;57532:332;;57561:13;57532:332;57626:7;57647:11;:23;;;57684:11;:23;;;57721:11;:21;;;57756:11;:24;;;57794:11;:22;;;57830:11;:24;;;57532:332;;;;;;;;;;;;:::i;:::-;;;;;;;;57439:432;57339:532;;;:::o;42543:279::-;41190:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41159:71;;;;;;;11835:2:1;41159:71:0;;;11817:21:1;11874:2;11854:18;;;11847:30;11913:26;11893:18;;;11886:54;11957:18;;41159:71:0;11633:348:1;41159:71:0;40513:6:::1;42631:10;:26;;42623:55;;;::::0;::::1;::::0;;16702:2:1;42623:55:0::1;::::0;::::1;16684:21:1::0;16741:2;16721:18;;;16714:30;16780:18;16760;;;16753:46;16816:18;;42623:55:0::1;16500:340:1::0;42623:55:0::1;42709:15;::::0;;42734:28;;;;42777:38:::1;::::0;;17019:25:1;;;17075:2;17060:18;;17053:34;;;42777:38:0::1;::::0;16992:18:1;42777:38:0::1;;;;;;;;42613:209;42543:279:::0;:::o;43182:253::-;41190:10;33399:4;33422:29;;;:12;;:29;:12;:29;;;;;41159:71;;;;;;;11835:2:1;41159:71:0;;;11817:21:1;11874:2;11854:18;;;11847:30;11913:26;11893:18;;;11886:54;11957:18;;41159:71:0;11633:348:1;41159:71:0;43296:14:::1;::::0;;43320:34;;;;43369:59:::1;::::0;;17019:25:1;;;17075:2;17060:18;;17053:34;;;43369:59:0::1;::::0;16992:18:1;43369:59:0::1;16845:248:1::0;41934:187:0;42026:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41990:48;;;;;;42048:31;40329:23;42072:6;42048:11;:31::i;:::-;-1:-1:-1;42094:20:0;;12565:42:1;12553:55;;12535:74;;42094:20:0;;12523:2:1;12508:18;42094:20:0;12389:226:1;57877:460:0;58186:144;;;17413:10:1;17401:23;;17383:42;;58186:144:0;17522:15:1;;;17517:2;17502:18;;17495:43;17574:15;;;17554:18;;;17547:43;17621:2;17606:18;;17599:34;;;17664:3;17649:19;;17642:35;;;17708:3;17693:19;;17686:35;;;58186:144:0;;;;;;;;;58213:13;;58186:144;;;;;17370:3:1;58186:144:0;;;57877:460;;;;;;;;;:::o;35110:138::-;34343:7;34369:12;;;;;;;;;;:22;;;32932:16;32943:4;32932:10;:16::i;:::-;35215:26:::1;35227:4;35233:7;35215:11;:26::i;41343:193::-:0;41436:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;41400:48;;;;;;41458:34;40261:25;41483:8;41458:10;:34::i;:::-;-1:-1:-1;41507:22:0;;12565:42:1;12553:55;;12535:74;;41507:22:0;;12523:2:1;12508:18;41507:22:0;12389:226:1;42332:205:0;42430:10;32700:4;33422:29;;;:12;;:29;:12;:29;;;;;42394:48;;;;;;42452:37;40398:26;42479:9;42452:11;:37::i;:::-;-1:-1:-1;42504:26:0;;12565:42:1;12553:55;;12535:74;;42504:26:0;;12523:2:1;12508:18;42504:26:0;12389:226:1;37945:653:0;38120:4;38106:19;;;;38102:32;;37945:653;;;:::o;38102:32::-;38206:5;38215:1;38206:10;38202:23;;37945:653;;;:::o;38202:23::-;38238:20;;;;;38234:358;;38418:12;38435:2;:7;;38450:5;38435:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38417:43;;;38482:7;38474:39;;;;;;;18144:2:1;38474:39:0;;;18126:21:1;18183:2;18163:18;;;18156:30;18222:21;18202:18;;;18195:49;18261:18;;38474:39:0;17942:343:1;38234:358:0;38544:37;:26;;;38571:2;38575:5;38544:26;:37::i;33667:103::-;33733:30;33744:4;22980:10;33733;:30::i;:::-;33667:103;:::o;36647:316::-;36724:4;33422:12;;;;;;;;;;;:29;;;;;;;;;;;;;36740:217;;36783:6;:12;;;;;;;;;;;:29;;;;;;;;;;:36;;;;36815:4;36783:36;;;36865:12;22980:10;;22901:96;36865:12;36838:40;;36856:7;36838:40;;36850:4;36838:40;;;;;;;;;;-1:-1:-1;36899:4:0;36892:11;;36740:217;-1:-1:-1;36941:5:0;36934:12;;37198:317;37276:4;33422:12;;;;;;;;;;;:29;;;;;;;;;;;;;37292:217;;;37366:5;37334:12;;;;;;;;;;;:29;;;;;;;;;;;:37;;;;;;37390:40;22980:10;;37334:12;;37390:40;;37366:5;37390:40;-1:-1:-1;37451:4:0;37444:11;;26150:160;26259:43;;;26274:14;18482:55:1;;26259:43:0;;;18464:74:1;18554:18;;;;18547:34;;;26259:43:0;;;;;;;;;;18437:18:1;;;;26259:43:0;;;;;;;;;;;;;;26232:71;;26252:5;;26232:19;:71::i;33900:197::-;33399:4;33422:12;;;;;;;;;;;:29;;;;;;;;;;;;;33983:108;;34033:47;;;;;18494:42:1;18482:55;;34033:47:0;;;18464:74:1;18554:18;;;18547:34;;;18437:18;;34033:47:0;18290:297:1;28906:629:0;29325:23;29351:33;:27;;;29379:4;29351:27;:33::i;:::-;29325:59;;29398:10;:17;29419:1;29398:22;;:57;;;;;29436:10;29425:30;;;;;;;;;;;;:::i;:::-;29424:31;29398:57;29394:135;;;29478:40;;;;;12565:42:1;12553:55;;29478:40:0;;;12535:74:1;12508:18;;29478:40:0;12389:226:1;18686:151:0;18761:12;18792:38;18814:6;18822:4;18828:1;18792:21;:38::i;:::-;18785:45;18686:151;-1:-1:-1;;;18686:151:0:o;19161:392::-;19260:12;19312:5;19288:21;:29;19284:108;;;19340:41;;;;;19375:4;19340:41;;;12535:74:1;12508:18;;19340:41:0;12389:226:1;19284:108:0;19402:12;19416:23;19443:6;:11;;19462:5;19469:4;19443:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19401:73;;;;19491:55;19518:6;19526:7;19535:10;19491:26;:55::i;:::-;19484:62;19161:392;-1:-1:-1;;;;;;19161:392:0:o;20606:582::-;20750:12;20779:7;20774:408;;20802:19;20810:10;20802:7;:19::i;:::-;20774:408;;;21026:17;;:22;:49;;;;-1:-1:-1;21052:18:0;;;;:23;21026:49;21022:119;;;21102:24;;;;;12565:42:1;12553:55;;21102:24:0;;;12535:74:1;12508:18;;21102:24:0;12389:226:1;21022:119:0;-1:-1:-1;21161:10:0;21154:17;;21724:516;21855:17;;:21;21851:383;;22083:10;22077:17;22139:15;22126:10;22122:2;22118:19;22111:44;21851:383;22206:17;;;;;;;;;;;;;;14:332:1;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;180:9;167:23;230:66;223:5;219:78;212:5;209:89;199:117;;312:1;309;302:12;821:154;907:42;900:5;896:54;889:5;886:65;876:93;;965:1;962;955:12;980:134;1048:20;;1077:31;1048:20;1077:31;:::i;:::-;980:134;;;:::o;1119:388::-;1187:6;1195;1248:2;1236:9;1227:7;1223:23;1219:32;1216:52;;;1264:1;1261;1254:12;1216:52;1303:9;1290:23;1322:31;1347:5;1322:31;:::i;:::-;1372:5;-1:-1:-1;1429:2:1;1414:18;;1401:32;1442:33;1401:32;1442:33;:::i;:::-;1494:7;1484:17;;;1119:388;;;;;:::o;1694:180::-;1753:6;1806:2;1794:9;1785:7;1781:23;1777:32;1774:52;;;1822:1;1819;1812:12;1774:52;-1:-1:-1;1845:23:1;;1694:180;-1:-1:-1;1694:180:1:o;1879:315::-;1947:6;1955;2008:2;1996:9;1987:7;1983:23;1979:32;1976:52;;;2024:1;2021;2014:12;1976:52;2060:9;2047:23;2037:33;;2120:2;2109:9;2105:18;2092:32;2133:31;2158:5;2133:31;:::i;2199:247::-;2258:6;2311:2;2299:9;2290:7;2286:23;2282:32;2279:52;;;2327:1;2324;2317:12;2279:52;2366:9;2353:23;2385:31;2410:5;2385:31;:::i;2451:184::-;2503:77;2500:1;2493:88;2600:4;2597:1;2590:15;2624:4;2621:1;2614:15;2640:250;2707:2;2701:9;2749:6;2737:19;;2786:18;2771:34;;2807:22;;;2768:62;2765:88;;;2833:18;;:::i;:::-;2869:2;2862:22;2640:250;:::o;2895:252::-;2967:2;2961:9;3009:3;2997:16;;3043:18;3028:34;;3064:22;;;3025:62;3022:88;;;3090:18;;:::i;3152:777::-;3194:5;3247:3;3240:4;3232:6;3228:17;3224:27;3214:55;;3265:1;3262;3255:12;3214:55;3301:6;3288:20;3327:18;3364:2;3360;3357:10;3354:36;;;3370:18;;:::i;:::-;3504:2;3498:9;3566:4;3558:13;;3409:66;3554:22;;;3578:2;3550:31;3546:40;3534:53;;;3602:18;;;3622:22;;;3599:46;3596:72;;;3648:18;;:::i;:::-;3688:10;3684:2;3677:22;3723:2;3715:6;3708:18;3769:3;3762:4;3757:2;3749:6;3745:15;3741:26;3738:35;3735:55;;;3786:1;3783;3776:12;3735:55;3850:2;3843:4;3835:6;3831:17;3824:4;3816:6;3812:17;3799:54;3897:1;3890:4;3885:2;3877:6;3873:15;3869:26;3862:37;3917:6;3908:15;;;;;;3152:777;;;;:::o;3934:455::-;4011:6;4019;4072:2;4060:9;4051:7;4047:23;4043:32;4040:52;;;4088:1;4085;4078:12;4040:52;4128:9;4115:23;4161:18;4153:6;4150:30;4147:50;;;4193:1;4190;4183:12;4147:50;4216:49;4257:7;4248:6;4237:9;4233:22;4216:49;:::i;:::-;4206:59;;;4315:2;4304:9;4300:18;4287:32;4328:31;4353:5;4328:31;:::i;4394:121::-;4479:10;4472:5;4468:22;4461:5;4458:33;4448:61;;4505:1;4502;4495:12;4520:132;4587:20;;4616:30;4587:20;4616:30;:::i;4657:118::-;4743:5;4736:13;4729:21;4722:5;4719:32;4709:60;;4765:1;4762;4755:12;4780:128;4845:20;;4874:28;4845:20;4874:28;:::i;4913:801::-;4972:5;5020:6;5008:9;5003:3;4999:19;4995:32;4992:52;;;5040:1;5037;5030:12;4992:52;5062:17;;:::i;:::-;5053:26;;5102:28;5120:9;5102:28;:::i;:::-;5095:5;5088:43;5163:38;5197:2;5186:9;5182:18;5163:38;:::i;:::-;5158:2;5151:5;5147:14;5140:62;5234:38;5268:2;5257:9;5253:18;5234:38;:::i;:::-;5229:2;5222:5;5218:14;5211:62;5305:38;5339:2;5328:9;5324:18;5305:38;:::i;:::-;5300:2;5293:5;5289:14;5282:62;5377:39;5411:3;5400:9;5396:19;5377:39;:::i;:::-;5371:3;5364:5;5360:15;5353:64;5478:3;5467:9;5463:19;5450:33;5444:3;5437:5;5433:15;5426:58;5545:3;5534:9;5530:19;5517:33;5511:3;5504:5;5500:15;5493:58;5584:36;5615:3;5604:9;5600:19;5584:36;:::i;:::-;5578:3;5571:5;5567:15;5560:61;5640:3;5703:2;5692:9;5688:18;5675:32;5670:2;5663:5;5659:14;5652:56;;4913:801;;;;:::o;5719:237::-;5807:6;5860:3;5848:9;5839:7;5835:23;5831:33;5828:53;;;5877:1;5874;5867:12;5828:53;5900:50;5942:7;5931:9;5900:50;:::i;5961:320::-;6029:6;6082:2;6070:9;6061:7;6057:23;6053:32;6050:52;;;6098:1;6095;6088:12;6050:52;6138:9;6125:23;6171:18;6163:6;6160:30;6157:50;;;6203:1;6200;6193:12;6157:50;6226:49;6267:7;6258:6;6247:9;6243:22;6226:49;:::i;:::-;6216:59;5961:320;-1:-1:-1;;;;5961:320:1:o;6286:273::-;6362:6;6415:2;6403:9;6394:7;6390:23;6386:32;6383:52;;;6431:1;6428;6421:12;6383:52;6470:9;6457:23;6509:1;6502:5;6499:12;6489:40;;6525:1;6522;6515:12;6564:250;6649:1;6659:113;6673:6;6670:1;6667:13;6659:113;;;6749:11;;;6743:18;6730:11;;;6723:39;6695:2;6688:10;6659:113;;;-1:-1:-1;;6806:1:1;6788:16;;6781:27;6564:250::o;6819:330::-;6861:3;6899:5;6893:12;6926:6;6921:3;6914:19;6942:76;7011:6;7004:4;6999:3;6995:14;6988:4;6981:5;6977:16;6942:76;:::i;:::-;7063:2;7051:15;7068:66;7047:88;7038:98;;;;7138:4;7034:109;;6819:330;-1:-1:-1;;6819:330:1:o;7154:220::-;7303:2;7292:9;7285:21;7266:4;7323:45;7364:2;7353:9;7349:18;7341:6;7323:45;:::i;7379:388::-;7456:6;7464;7517:2;7505:9;7496:7;7492:23;7488:32;7485:52;;;7533:1;7530;7523:12;7485:52;7573:9;7560:23;7606:18;7598:6;7595:30;7592:50;;;7638:1;7635;7628:12;7592:50;7661:49;7702:7;7693:6;7682:9;7678:22;7661:49;:::i;:::-;7651:59;7757:2;7742:18;;;;7729:32;;-1:-1:-1;;;;7379:388:1:o;8003:1375::-;8236:13;;7848:10;7837:22;7825:35;;8205:3;8190:19;;8308:4;8300:6;8296:17;8290:24;8323:53;8370:4;8359:9;8355:20;8341:12;7848:10;7837:22;7825:35;;7772:94;8323:53;;8425:4;8417:6;8413:17;8407:24;8440:56;8490:4;8479:9;8475:20;8459:14;7948:42;7937:54;7925:67;;7871:127;8440:56;;8545:4;8537:6;8533:17;8527:24;8560:56;8610:4;8599:9;8595:20;8579:14;7948:42;7937:54;7925:67;;7871:127;8560:56;;8665:4;8657:6;8653:17;8647:24;8680:56;8730:4;8719:9;8715:20;8699:14;7948:42;7937:54;7925:67;;7871:127;8680:56;;8785:4;8777:6;8773:17;8767:24;8800:56;8850:4;8839:9;8835:20;8819:14;7948:42;7937:54;7925:67;;7871:127;8800:56;;8912:4;8904:6;8900:17;8894:24;8887:4;8876:9;8872:20;8865:54;8975:4;8967:6;8963:17;8957:24;8950:4;8939:9;8935:20;8928:54;9001:6;9061:2;9053:6;9049:15;9043:22;9038:2;9027:9;9023:18;9016:50;;9085:6;9140:2;9132:6;9128:15;9122:22;9153:51;9200:2;9189:9;9185:18;9169:14;421:13;414:21;402:34;;351:91;9153:51;-1:-1:-1;;9223:6:1;9271:15;;;9265:22;9245:18;;;9238:50;9307:6;9355:15;;;9349:22;9329:18;;;;9322:50;;;;8003:1375;:::o;9383:440::-;9489:6;9497;9505;9558:3;9546:9;9537:7;9533:23;9529:33;9526:53;;;9575:1;9572;9565:12;9526:53;9611:9;9598:23;9588:33;;9671:2;9660:9;9656:18;9643:32;9684:31;9709:5;9684:31;:::i;:::-;9734:5;-1:-1:-1;9758:59:1;9809:7;9804:2;9789:18;;9758:59;:::i;:::-;9748:69;;9383:440;;;;;:::o;9828:523::-;9914:6;9922;9930;9983:2;9971:9;9962:7;9958:23;9954:32;9951:52;;;9999:1;9996;9989:12;9951:52;10035:9;10022:23;10012:33;;10095:2;10084:9;10080:18;10067:32;10108:31;10133:5;10108:31;:::i;:::-;10158:5;-1:-1:-1;10214:2:1;10199:18;;10186:32;10241:18;10230:30;;10227:50;;;10273:1;10270;10263:12;10227:50;10296:49;10337:7;10328:6;10317:9;10313:22;10296:49;:::i;:::-;10286:59;;;9828:523;;;;;:::o;10541:1087::-;10671:6;10679;10687;10695;10703;10711;10719;10727;10735;10788:3;10776:9;10767:7;10763:23;10759:33;10756:53;;;10805:1;10802;10795:12;10756:53;10841:9;10828:23;10818:33;;10901:2;10890:9;10886:18;10873:32;10914:31;10939:5;10914:31;:::i;:::-;10964:5;-1:-1:-1;11021:2:1;11006:18;;10993:32;11034:33;10993:32;11034:33;:::i;:::-;11086:7;-1:-1:-1;11145:2:1;11130:18;;11117:32;11158;11117;11158;:::i;:::-;11209:7;-1:-1:-1;11268:3:1;11253:19;;11240:33;11282;11240;11282;:::i;:::-;11334:7;-1:-1:-1;11393:3:1;11378:19;;11365:33;11407;11365;11407;:::i;:::-;11459:7;11449:17;;;11513:3;11502:9;11498:19;11485:33;11475:43;;11565:3;11554:9;11550:19;11537:33;11527:43;;11617:3;11606:9;11602:19;11589:33;11579:43;;10541:1087;;;;;;;;;;;:::o;12964:184::-;13016:77;13013:1;13006:88;13113:4;13110:1;13103:15;13137:4;13134:1;13127:15;13153:136;13231:13;;13253:30;13231:13;13253:30;:::i;13294:138::-;13373:13;;13395:31;13373:13;13395:31;:::i;13437:132::-;13513:13;;13535:28;13513:13;13535:28;:::i;13574:1189::-;13678:6;13731:3;13719:9;13710:7;13706:23;13702:33;13699:53;;;13748:1;13745;13738:12;13699:53;13774:22;;:::i;:::-;13819:39;13848:9;13819:39;:::i;:::-;13812:5;13805:54;13891:48;13935:2;13924:9;13920:18;13891:48;:::i;:::-;13886:2;13879:5;13875:14;13868:72;13972:49;14017:2;14006:9;14002:18;13972:49;:::i;:::-;13967:2;13960:5;13956:14;13949:73;14054:49;14099:2;14088:9;14084:18;14054:49;:::i;:::-;14049:2;14042:5;14038:14;14031:73;14137:50;14182:3;14171:9;14167:19;14137:50;:::i;:::-;14131:3;14124:5;14120:15;14113:75;14221:50;14266:3;14255:9;14251:19;14221:50;:::i;:::-;14215:3;14208:5;14204:15;14197:75;14326:3;14315:9;14311:19;14305:26;14299:3;14292:5;14288:15;14281:51;14386:3;14375:9;14371:19;14365:26;14359:3;14352:5;14348:15;14341:51;14411:3;14467:2;14456:9;14452:18;14446:25;14441:2;14434:5;14430:14;14423:49;;14491:3;14526:46;14568:2;14557:9;14553:18;14526:46;:::i;:::-;14510:14;;;14503:70;14592:3;14633:18;;;14627:25;14611:14;;;14604:49;14672:3;14713:18;;;14707:25;14691:14;;;14684:49;;;;-1:-1:-1;14514:5:1;13574:1189;-1:-1:-1;13574:1189:1:o;14768:184::-;14820:77;14817:1;14810:88;14917:4;14914:1;14907:15;14941:4;14938:1;14931:15;14957:168;15030:9;;;15061;;15078:15;;;15072:22;;15058:37;15048:71;;15099:18;;:::i;15130:274::-;15170:1;15196;15186:189;;15231:77;15228:1;15221:88;15332:4;15329:1;15322:15;15360:4;15357:1;15350:15;15186:189;-1:-1:-1;15389:9:1;;15130:274::o;15409:128::-;15476:9;;;15497:11;;;15494:37;;;15511:18;;:::i;15542:195::-;15581:3;15612:66;15605:5;15602:77;15599:103;;15682:18;;:::i;:::-;-1:-1:-1;15729:1:1;15718:13;;15542:195::o;15742:753::-;16049:3;16038:9;16031:22;16012:4;16070:46;16111:3;16100:9;16096:19;16088:6;16070:46;:::i;:::-;16164:10;16152:23;;;;16147:2;16132:18;;16125:51;-1:-1:-1;16195:42:1;16273:15;;;16268:2;16253:18;;16246:43;16325:15;;;;16320:2;16305:18;;16298:43;16372:3;16357:19;;16350:35;;;;16416:3;16401:19;;16394:35;16473:14;;16466:22;16460:3;16445:19;;;16438:51;16062:54;15742:753;-1:-1:-1;15742:753:1:o;18894:245::-;18961:6;19014:2;19002:9;18993:7;18989:23;18985:32;18982:52;;;19030:1;19027;19020:12;18982:52;19062:9;19056:16;19081:28;19103:5;19081:28;:::i;19144:287::-;19273:3;19311:6;19305:13;19327:66;19386:6;19381:3;19374:4;19366:6;19362:17;19327:66;:::i;:::-;19409:16;;;;;19144:287;-1:-1:-1;;19144:287:1:o","abiDefinition":[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositRefunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"}],"name":"BridgeProofDisputed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":false,"internalType":"bytes32","name":"transactionHash","type":"bytes32"}],"name":"BridgeProofProvided","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint32","name":"originChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"chainGasAmount","type":"uint256"}],"name":"BridgeRelayed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes","name":"request","type":"bytes"},{"indexed":false,"internalType":"uint32","name":"destChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"sendChainGas","type":"bool"}],"name":"BridgeRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldChainGasAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"ChainGasAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFeeRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"FeeRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesSwept","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"governor","type":"address"}],"name":"GovernorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"governor","type":"address"}],"name":"GovernorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guard","type":"address"}],"name":"GuardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guard","type":"address"}],"name":"GuardRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_RATE_MAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GOVERNOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GUARD_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAYER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_governor","type":"address"}],"name":"addGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guard","type":"address"}],"name":"addGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_relayer","type":"address"}],"name":"addRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstChainId","type":"uint32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IFastBridge.BridgeParams","name":"params","type":"tuple"}],"name":"bridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionid","type":"bytes32"},{"internalType":"address","name":"relayer","type":"address"}],"name":"canClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainGasAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"address","name":"to","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deployBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"dispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"getBridgeTransaction","outputs":[{"components":[{"internalType":"uint32","name":"originChainId","type":"uint32"},{"internalType":"uint32","name":"destChainId","type":"uint32"},{"internalType":"address","name":"originSender","type":"address"},{"internalType":"address","name":"destRecipient","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256","name":"originFeeAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct IFastBridge.BridgeTransaction","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"enum FastBridge.BridgeStatus","name":"keyValue","type":"uint8"}],"name":"getEnumKeyByValue","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"address","name":"relayer","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint32","name":"originChainId","type":"uint32"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256","name":"chainGasAmount","type":"uint256"}],"name":"mockBridgeRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"},{"components":[{"internalType":"uint32","name":"dstChainId","type":"uint32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IFastBridge.BridgeParams","name":"params","type":"tuple"}],"name":"mockBridgeRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"bytes","name":"request","type":"bytes"}],"name":"mockBridgeRequestRaw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"protocolFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"bytes32","name":"destTxHash","type":"bytes32"}],"name":"prove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"relay","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_governor","type":"address"}],"name":"removeGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guard","type":"address"}],"name":"removeGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_relayer","type":"address"}],"name":"removeRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"setChainGasAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"setProtocolFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"sweepProtocolFees","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"notice":"Initiates bridge on origin chain to be relayed by off-chain relayer"},"chainGasAmount()":{"notice":"Chain gas amount to forward as rebate if requested"},"claim(bytes,address)":{"notice":"Completes bridge transaction on origin chain by claiming originally deposited capital"},"dispute(bytes32)":{"notice":"Disputes an outstanding proof in case relayer provided dest chain tx is invalid"},"getBridgeTransaction(bytes)":{"notice":"Decodes bridge request into a bridge transaction"},"protocolFeeRate()":{"notice":"Protocol fee rate taken on origin amount deposited in origin chain"},"protocolFees(address)":{"notice":"Protocol fee amounts accumulated"},"prove(bytes,bytes32)":{"notice":"Provides proof on origin side that relayer provided funds on destination side of bridge transaction"},"refund(bytes)":{"notice":"Refunds an outstanding bridge transaction in case optimistic bridging failed"},"relay(bytes)":{"notice":"Relays destination side of bridge transaction by off-chain relayer"}},"version":1},"developerDoc":{"errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}],"AddressEmptyCode(address)":[{"details":"There's no code at `target` (it is not a contract)."}],"AddressInsufficientBalance(address)":[{"details":"The ETH balance of the account is not enough to perform the operation."}],"FailedInnerCall()":[{"details":"A call to an address target failed. The target may have reverted."}],"SafeERC20FailedOperation(address)":[{"details":"An operation with an ERC-20 token failed."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"params":{"params":"The parameters required to bridge"}},"claim(bytes,address)":{"params":{"request":"The encoded bridge transaction to claim on origin chain","to":"The recipient address of the funds"}},"dispute(bytes32)":{"params":{"transactionId":"The transaction id associated with the encoded bridge transaction to dispute"}},"getBridgeTransaction(bytes)":{"params":{"request":"The bridge request to decode"}},"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"prove(bytes,bytes32)":{"params":{"destTxHash":"The destination tx hash proving bridge transaction was relayed","request":"The encoded bridge transaction to prove on origin chain"}},"refund(bytes)":{"params":{"request":"The encoded bridge transaction to refund"}},"relay(bytes)":{"params":{"request":"The encoded bridge transaction to relay on destination chain"}},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"stateVariables":{"nonce":{"details":"to prevent replays"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositRefunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"BridgeProofDisputed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"transactionHash\",\"type\":\"bytes32\"}],\"name\":\"BridgeProofProvided\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"BridgeRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"}],\"name\":\"BridgeRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"addGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"addGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"addRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"bridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionid\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"canClaim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"dispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"getBridgeTransaction\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originSender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destRecipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originFeeAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeTransaction\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enum FastBridge.BridgeStatus\",\"name\":\"keyValue\",\"type\":\"uint8\"}],\"name\":\"getEnumKeyByValue\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"mockBridgeRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"mockBridgeRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"mockBridgeRequestRaw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"destTxHash\",\"type\":\"bytes32\"}],\"name\":\"prove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"refund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"removeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"removeGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"removeRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}],\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"AddressInsufficientBalance(address)\":[{\"details\":\"The ETH balance of the account is not enough to perform the operation.\"}],\"FailedInnerCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"params\":{\"params\":\"The parameters required to bridge\"}},\"claim(bytes,address)\":{\"params\":{\"request\":\"The encoded bridge transaction to claim on origin chain\",\"to\":\"The recipient address of the funds\"}},\"dispute(bytes32)\":{\"params\":{\"transactionId\":\"The transaction id associated with the encoded bridge transaction to dispute\"}},\"getBridgeTransaction(bytes)\":{\"params\":{\"request\":\"The bridge request to decode\"}},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"prove(bytes,bytes32)\":{\"params\":{\"destTxHash\":\"The destination tx hash proving bridge transaction was relayed\",\"request\":\"The encoded bridge transaction to prove on origin chain\"}},\"refund(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to refund\"}},\"relay(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to relay on destination chain\"}},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"stateVariables\":{\"nonce\":{\"details\":\"to prevent replays\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"notice\":\"Initiates bridge on origin chain to be relayed by off-chain relayer\"},\"chainGasAmount()\":{\"notice\":\"Chain gas amount to forward as rebate if requested\"},\"claim(bytes,address)\":{\"notice\":\"Completes bridge transaction on origin chain by claiming originally deposited capital\"},\"dispute(bytes32)\":{\"notice\":\"Disputes an outstanding proof in case relayer provided dest chain tx is invalid\"},\"getBridgeTransaction(bytes)\":{\"notice\":\"Decodes bridge request into a bridge transaction\"},\"protocolFeeRate()\":{\"notice\":\"Protocol fee rate taken on origin amount deposited in origin chain\"},\"protocolFees(address)\":{\"notice\":\"Protocol fee amounts accumulated\"},\"prove(bytes,bytes32)\":{\"notice\":\"Provides proof on origin side that relayer provided funds on destination side of bridge transaction\"},\"refund(bytes)\":{\"notice\":\"Refunds an outstanding bridge transaction in case optimistic bridging failed\"},\"relay(bytes)\":{\"notice\":\"Relays destination side of bridge transaction by off-chain relayer\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"FastBridgeMock\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0xfdd0a71cdd1fe45137a59bc8e7544699eb71ead398af2fd0f1cf448a878ccacd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://07ce767dbb21de80ca0b546310d3c374ed7ddcf5376c7085f15c7812f7678819\",\"dweb:/ipfs/QmQ3JUoivC7YRSxZnRstRKmJJ8x8cLLhEbgWsiXV5NmYrs\"]}},\"version\":1}"},"hashes":{"DEFAULT_ADMIN_ROLE()":"a217fddf","FEE_BPS()":"bf333f2c","FEE_RATE_MAX()":"0f5f6ed7","GOVERNOR_ROLE()":"ccc57490","GUARD_ROLE()":"03ed0ee5","RELAYER_ROLE()":"926d7d7f","addGovernor(address)":"3c4a25d0","addGuard(address)":"6913a63c","addRelayer(address)":"dd39f00d","bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":"45851694","canClaim(bytes32,address)":"aa9641ab","chainGasAmount()":"e00a83e0","claim(bytes,address)":"41fcb612","deployBlock()":"a3ec191a","dispute(bytes32)":"add98c70","getBridgeTransaction(bytes)":"ac11fb1a","getEnumKeyByValue(uint8)":"85ad903d","getRoleAdmin(bytes32)":"248a9ca3","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","mockBridgeRelayer(bytes32,address,address,uint32,address,address,uint256,uint256,uint256)":"c72870cc","mockBridgeRequest(bytes32,address,(uint32,address,address,address,address,uint256,uint256,bool,uint256))":"acaebbf1","mockBridgeRequestRaw(bytes32,address,bytes)":"aedf009d","nonce()":"affed0e0","protocolFeeRate()":"58f85880","protocolFees(address)":"dcf844a7","prove(bytes,bytes32)":"886d36ff","refund(bytes)":"5eb7d946","relay(bytes)":"8f0d6f17","removeGovernor(address)":"eecdac88","removeGuard(address)":"b6235016","removeRelayer(address)":"60f0a5ac","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","setChainGasAmount(uint256)":"b250fe6b","setProtocolFeeRate(uint256)":"b13aa2d6","supportsInterface(bytes4)":"01ffc9a7","sweepProtocolFees(address,address)":"06f333f2"}},"solidity/FastBridgeMock.sol:IAccessControl":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n ) external {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"External interface of AccessControl declared to support ERC-165 detection.","errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {AccessControl-_setRoleAdmin}."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"External interface of AccessControl declared to support ERC-165 detection.\",\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {AccessControl-_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"IAccessControl\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0xfdd0a71cdd1fe45137a59bc8e7544699eb71ead398af2fd0f1cf448a878ccacd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://07ce767dbb21de80ca0b546310d3c374ed7ddcf5376c7085f15c7812f7678819\",\"dweb:/ipfs/QmQ3JUoivC7YRSxZnRstRKmJJ8x8cLLhEbgWsiXV5NmYrs\"]}},\"version\":1}"},"hashes":{"getRoleAdmin(bytes32)":"248a9ca3","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f"}},"solidity/FastBridgeMock.sol:IAdmin":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n ) external {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldChainGasAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"ChainGasAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFeeRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"FeeRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesSwept","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"governor","type":"address"}],"name":"GovernorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"governor","type":"address"}],"name":"GovernorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guard","type":"address"}],"name":"GuardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guard","type":"address"}],"name":"GuardRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerRemoved","type":"event"},{"inputs":[{"internalType":"address","name":"_governor","type":"address"}],"name":"addGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guard","type":"address"}],"name":"addGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_relayer","type":"address"}],"name":"addRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_governor","type":"address"}],"name":"removeGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guard","type":"address"}],"name":"removeGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_relayer","type":"address"}],"name":"removeRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"setChainGasAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"setProtocolFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"sweepProtocolFees","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"}],\"name\":\"GovernorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"}],\"name\":\"GuardRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"RelayerRemoved\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"addGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"addGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"addRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"removeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guard\",\"type\":\"address\"}],\"name\":\"removeGuard\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayer\",\"type\":\"address\"}],\"name\":\"removeRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"IAdmin\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0xfdd0a71cdd1fe45137a59bc8e7544699eb71ead398af2fd0f1cf448a878ccacd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://07ce767dbb21de80ca0b546310d3c374ed7ddcf5376c7085f15c7812f7678819\",\"dweb:/ipfs/QmQ3JUoivC7YRSxZnRstRKmJJ8x8cLLhEbgWsiXV5NmYrs\"]}},\"version\":1}"},"hashes":{"addGovernor(address)":"3c4a25d0","addGuard(address)":"6913a63c","addRelayer(address)":"dd39f00d","removeGovernor(address)":"eecdac88","removeGuard(address)":"b6235016","removeRelayer(address)":"60f0a5ac","setChainGasAmount(uint256)":"b250fe6b","setProtocolFeeRate(uint256)":"b13aa2d6","sweepProtocolFees(address,address)":"06f333f2"}},"solidity/FastBridgeMock.sol:IERC165":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n ) external {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Interface of the ERC-165 standard, as defined in the https://eips.ethereum.org/EIPS/eip-165[ERC]. Implementers can declare support of contract interfaces, which can then be queried by others ({ERC165Checker}). For an implementation, see {ERC165}.","kind":"dev","methods":{"supportsInterface(bytes4)":{"details":"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Interface of the ERC-165 standard, as defined in the https://eips.ethereum.org/EIPS/eip-165[ERC]. Implementers can declare support of contract interfaces, which can then be queried by others ({ERC165Checker}). For an implementation, see {ERC165}.\",\"kind\":\"dev\",\"methods\":{\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"IERC165\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0xfdd0a71cdd1fe45137a59bc8e7544699eb71ead398af2fd0f1cf448a878ccacd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://07ce767dbb21de80ca0b546310d3c374ed7ddcf5376c7085f15c7812f7678819\",\"dweb:/ipfs/QmQ3JUoivC7YRSxZnRstRKmJJ8x8cLLhEbgWsiXV5NmYrs\"]}},\"version\":1}"},"hashes":{"supportsInterface(bytes4)":"01ffc9a7"}},"solidity/FastBridgeMock.sol:IERC20":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n ) external {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Interface of the ERC-20 standard as defined in the ERC.","events":{"Approval(address,address,uint256)":{"details":"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance."},"Transfer(address,address,uint256)":{"details":"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero."}},"kind":"dev","methods":{"allowance(address,address)":{"details":"Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through {transferFrom}. This is zero by default. This value changes when {approve} or {transferFrom} are called."},"approve(address,uint256)":{"details":"Sets a `value` amount of tokens as the allowance of `spender` over the caller's tokens. Returns a boolean value indicating whether the operation succeeded. IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 Emits an {Approval} event."},"balanceOf(address)":{"details":"Returns the value of tokens owned by `account`."},"totalSupply()":{"details":"Returns the value of tokens in existence."},"transfer(address,uint256)":{"details":"Moves a `value` amount of tokens from the caller's account to `to`. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event."},"transferFrom(address,address,uint256)":{"details":"Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism. `value` is then deducted from the caller's allowance. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Interface of the ERC-20 standard as defined in the ERC.\",\"events\":{\"Approval(address,address,uint256)\":{\"details\":\"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance.\"},\"Transfer(address,address,uint256)\":{\"details\":\"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero.\"}},\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through {transferFrom}. This is zero by default. This value changes when {approve} or {transferFrom} are called.\"},\"approve(address,uint256)\":{\"details\":\"Sets a `value` amount of tokens as the allowance of `spender` over the caller's tokens. Returns a boolean value indicating whether the operation succeeded. IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 Emits an {Approval} event.\"},\"balanceOf(address)\":{\"details\":\"Returns the value of tokens owned by `account`.\"},\"totalSupply()\":{\"details\":\"Returns the value of tokens in existence.\"},\"transfer(address,uint256)\":{\"details\":\"Moves a `value` amount of tokens from the caller's account to `to`. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism. `value` is then deducted from the caller's allowance. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"IERC20\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0xfdd0a71cdd1fe45137a59bc8e7544699eb71ead398af2fd0f1cf448a878ccacd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://07ce767dbb21de80ca0b546310d3c374ed7ddcf5376c7085f15c7812f7678819\",\"dweb:/ipfs/QmQ3JUoivC7YRSxZnRstRKmJJ8x8cLLhEbgWsiXV5NmYrs\"]}},\"version\":1}"},"hashes":{"allowance(address,address)":"dd62ed3e","approve(address,uint256)":"095ea7b3","balanceOf(address)":"70a08231","totalSupply()":"18160ddd","transfer(address,uint256)":"a9059cbb","transferFrom(address,address,uint256)":"23b872dd"}},"solidity/FastBridgeMock.sol:IERC20Permit":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n ) external {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in https://eips.ethereum.org/EIPS/eip-2612[ERC-2612]. Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't need to send a transaction, and thus is not required to hold Ether at all. ==== Security Considerations There are two important considerations concerning the use of `permit`. The first is that a valid permit signature expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be considered as an intention to spend the allowance in any specific way. The second is that because permits have built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be generally recommended is: ```solidity function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} doThing(..., value); } function doThing(..., uint256 value) public { token.safeTransferFrom(msg.sender, address(this), value); ... } ``` Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also {SafeERC20-safeTransferFrom}). Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so contracts should have entry points that don't rely on permit.","kind":"dev","methods":{"DOMAIN_SEPARATOR()":{"details":"Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}."},"nonces(address)":{"details":"Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times."},"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)":{"details":"Sets `value` as the allowance of `spender` over ``owner``'s tokens, given ``owner``'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. CAUTION: See Security Considerations above."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in https://eips.ethereum.org/EIPS/eip-2612[ERC-2612]. Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't need to send a transaction, and thus is not required to hold Ether at all. ==== Security Considerations There are two important considerations concerning the use of `permit`. The first is that a valid permit signature expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be considered as an intention to spend the allowance in any specific way. The second is that because permits have built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be generally recommended is: ```solidity function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} doThing(..., value); } function doThing(..., uint256 value) public { token.safeTransferFrom(msg.sender, address(this), value); ... } ``` Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also {SafeERC20-safeTransferFrom}). Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so contracts should have entry points that don't rely on permit.\",\"kind\":\"dev\",\"methods\":{\"DOMAIN_SEPARATOR()\":{\"details\":\"Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\"},\"nonces(address)\":{\"details\":\"Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times.\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Sets `value` as the allowance of `spender` over ``owner``'s tokens, given ``owner``'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. CAUTION: See Security Considerations above.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"IERC20Permit\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0xfdd0a71cdd1fe45137a59bc8e7544699eb71ead398af2fd0f1cf448a878ccacd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://07ce767dbb21de80ca0b546310d3c374ed7ddcf5376c7085f15c7812f7678819\",\"dweb:/ipfs/QmQ3JUoivC7YRSxZnRstRKmJJ8x8cLLhEbgWsiXV5NmYrs\"]}},\"version\":1}"},"hashes":{"DOMAIN_SEPARATOR()":"3644e515","nonces(address)":"7ecebe00","permit(address,address,uint256,uint256,uint8,bytes32,bytes32)":"d505accf"}},"solidity/FastBridgeMock.sol:IFastBridge":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n ) external {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositRefunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"}],"name":"BridgeProofDisputed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":false,"internalType":"bytes32","name":"transactionHash","type":"bytes32"}],"name":"BridgeProofProvided","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint32","name":"originChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"chainGasAmount","type":"uint256"}],"name":"BridgeRelayed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes","name":"request","type":"bytes"},{"indexed":false,"internalType":"uint32","name":"destChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"sendChainGas","type":"bool"}],"name":"BridgeRequested","type":"event"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstChainId","type":"uint32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IFastBridge.BridgeParams","name":"params","type":"tuple"}],"name":"bridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"address","name":"relayer","type":"address"}],"name":"canClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"address","name":"to","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"dispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"getBridgeTransaction","outputs":[{"components":[{"internalType":"uint32","name":"originChainId","type":"uint32"},{"internalType":"uint32","name":"destChainId","type":"uint32"},{"internalType":"address","name":"originSender","type":"address"},{"internalType":"address","name":"destRecipient","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256","name":"originFeeAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct IFastBridge.BridgeTransaction","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"bytes32","name":"destTxHash","type":"bytes32"}],"name":"prove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"relay","outputs":[],"stateMutability":"payable","type":"function"}],"userDoc":{"kind":"user","methods":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"notice":"Initiates bridge on origin chain to be relayed by off-chain relayer"},"canClaim(bytes32,address)":{"notice":"Checks if the dispute period has passed so bridge deposit can be claimed"},"claim(bytes,address)":{"notice":"Completes bridge transaction on origin chain by claiming originally deposited capital"},"dispute(bytes32)":{"notice":"Disputes an outstanding proof in case relayer provided dest chain tx is invalid"},"getBridgeTransaction(bytes)":{"notice":"Decodes bridge request into a bridge transaction"},"prove(bytes,bytes32)":{"notice":"Provides proof on origin side that relayer provided funds on destination side of bridge transaction"},"refund(bytes)":{"notice":"Refunds an outstanding bridge transaction in case optimistic bridging failed"},"relay(bytes)":{"notice":"Relays destination side of bridge transaction by off-chain relayer"}},"version":1},"developerDoc":{"kind":"dev","methods":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"params":{"params":"The parameters required to bridge"}},"canClaim(bytes32,address)":{"params":{"relayer":"The address of the relayer attempting to claim","transactionId":"The transaction id associated with the encoded bridge transaction to check"}},"claim(bytes,address)":{"params":{"request":"The encoded bridge transaction to claim on origin chain","to":"The recipient address of the funds"}},"dispute(bytes32)":{"params":{"transactionId":"The transaction id associated with the encoded bridge transaction to dispute"}},"getBridgeTransaction(bytes)":{"params":{"request":"The bridge request to decode"}},"prove(bytes,bytes32)":{"params":{"destTxHash":"The destination tx hash proving bridge transaction was relayed","request":"The encoded bridge transaction to prove on origin chain"}},"refund(bytes)":{"params":{"request":"The encoded bridge transaction to refund"}},"relay(bytes)":{"params":{"request":"The encoded bridge transaction to relay on destination chain"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositRefunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"BridgeProofDisputed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"transactionHash\",\"type\":\"bytes32\"}],\"name\":\"BridgeProofProvided\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"BridgeRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"}],\"name\":\"BridgeRequested\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"bridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"canClaim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"dispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"getBridgeTransaction\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originSender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destRecipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originFeeAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeTransaction\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"destTxHash\",\"type\":\"bytes32\"}],\"name\":\"prove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"refund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"params\":{\"params\":\"The parameters required to bridge\"}},\"canClaim(bytes32,address)\":{\"params\":{\"relayer\":\"The address of the relayer attempting to claim\",\"transactionId\":\"The transaction id associated with the encoded bridge transaction to check\"}},\"claim(bytes,address)\":{\"params\":{\"request\":\"The encoded bridge transaction to claim on origin chain\",\"to\":\"The recipient address of the funds\"}},\"dispute(bytes32)\":{\"params\":{\"transactionId\":\"The transaction id associated with the encoded bridge transaction to dispute\"}},\"getBridgeTransaction(bytes)\":{\"params\":{\"request\":\"The bridge request to decode\"}},\"prove(bytes,bytes32)\":{\"params\":{\"destTxHash\":\"The destination tx hash proving bridge transaction was relayed\",\"request\":\"The encoded bridge transaction to prove on origin chain\"}},\"refund(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to refund\"}},\"relay(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to relay on destination chain\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"notice\":\"Initiates bridge on origin chain to be relayed by off-chain relayer\"},\"canClaim(bytes32,address)\":{\"notice\":\"Checks if the dispute period has passed so bridge deposit can be claimed\"},\"claim(bytes,address)\":{\"notice\":\"Completes bridge transaction on origin chain by claiming originally deposited capital\"},\"dispute(bytes32)\":{\"notice\":\"Disputes an outstanding proof in case relayer provided dest chain tx is invalid\"},\"getBridgeTransaction(bytes)\":{\"notice\":\"Decodes bridge request into a bridge transaction\"},\"prove(bytes,bytes32)\":{\"notice\":\"Provides proof on origin side that relayer provided funds on destination side of bridge transaction\"},\"refund(bytes)\":{\"notice\":\"Refunds an outstanding bridge transaction in case optimistic bridging failed\"},\"relay(bytes)\":{\"notice\":\"Relays destination side of bridge transaction by off-chain relayer\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"IFastBridge\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0xfdd0a71cdd1fe45137a59bc8e7544699eb71ead398af2fd0f1cf448a878ccacd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://07ce767dbb21de80ca0b546310d3c374ed7ddcf5376c7085f15c7812f7678819\",\"dweb:/ipfs/QmQ3JUoivC7YRSxZnRstRKmJJ8x8cLLhEbgWsiXV5NmYrs\"]}},\"version\":1}"},"hashes":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":"45851694","canClaim(bytes32,address)":"aa9641ab","claim(bytes,address)":"41fcb612","dispute(bytes32)":"add98c70","getBridgeTransaction(bytes)":"ac11fb1a","prove(bytes,bytes32)":"886d36ff","refund(bytes)":"5eb7d946","relay(bytes)":"8f0d6f17"}},"solidity/FastBridgeMock.sol:SafeERC20":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212205eb4e090a6f6b36dc901d60cd1bbcfc48c2db77de14c95f950ce0b9585cba21f64736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212205eb4e090a6f6b36dc901d60cd1bbcfc48c2db77de14c95f950ce0b9585cba21f64736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n ) external {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"25597:5019:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;25597:5019:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"25597:5019:0:-:0;;;;;;;;","abiDefinition":[{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"currentAllowance","type":"uint256"},{"internalType":"uint256","name":"requestedDecrease","type":"uint256"}],"name":"SafeERC20FailedDecreaseAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Wrappers around ERC-20 operations that throw on failure (when the token contract returns false). Tokens that return no value (and instead revert or throw on failure) are also supported, non-reverting calls are assumed to be successful. To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, which allows you to call the safe operations as `token.safeTransfer(...)`, etc.","errors":{"SafeERC20FailedDecreaseAllowance(address,uint256,uint256)":[{"details":"Indicates a failed `decreaseAllowance` request."}],"SafeERC20FailedOperation(address)":[{"details":"An operation with an ERC-20 token failed."}]},"kind":"dev","methods":{},"title":"SafeERC20","version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"currentAllowance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestedDecrease\",\"type\":\"uint256\"}],\"name\":\"SafeERC20FailedDecreaseAllowance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"}],\"devdoc\":{\"details\":\"Wrappers around ERC-20 operations that throw on failure (when the token contract returns false). Tokens that return no value (and instead revert or throw on failure) are also supported, non-reverting calls are assumed to be successful. To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\",\"errors\":{\"SafeERC20FailedDecreaseAllowance(address,uint256,uint256)\":[{\"details\":\"Indicates a failed `decreaseAllowance` request.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}]},\"kind\":\"dev\",\"methods\":{},\"title\":\"SafeERC20\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"SafeERC20\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0xfdd0a71cdd1fe45137a59bc8e7544699eb71ead398af2fd0f1cf448a878ccacd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://07ce767dbb21de80ca0b546310d3c374ed7ddcf5376c7085f15c7812f7678819\",\"dweb:/ipfs/QmQ3JUoivC7YRSxZnRstRKmJJ8x8cLLhEbgWsiXV5NmYrs\"]}},\"version\":1}"},"hashes":{}},"solidity/FastBridgeMock.sol:UniversalTokenLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212208c262359b6648f7f4b885113d3ee31cd52f290219086243f6a491efdf608653264736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212208c262359b6648f7f4b885113d3ee31cd52f290219086243f6a491efdf608653264736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event RelayerAdded(address relayer);\n event RelayerRemoved(address relayer);\n\n event GuardAdded(address guard);\n event GuardRemoved(address guard);\n\n event GovernorAdded(address governor);\n event GovernorRemoved(address governor);\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function addRelayer(address _relayer) external;\n\n function removeRelayer(address _relayer) external;\n\n function addGuard(address _guard) external;\n\n function removeGuard(address _guard) external;\n\n function addGovernor(address _governor) external;\n\n function removeGovernor(address _governor) external;\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControl {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n modifier onlyGuard() {\n require(hasRole(GUARD_ROLE, msg.sender), \"Caller is not a guard\");\n _;\n }\n\n modifier onlyRelayer() {\n require(hasRole(RELAYER_ROLE, msg.sender), \"Caller is not a relayer\");\n _;\n }\n\n modifier onlyGovernor() {\n require(hasRole(GOVERNOR_ROLE, msg.sender), \"Caller is not a governor\");\n _;\n }\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function addRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(RELAYER_ROLE, _relayer);\n emit RelayerAdded(_relayer);\n }\n\n function removeRelayer(address _relayer) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(RELAYER_ROLE, _relayer);\n emit RelayerRemoved(_relayer);\n }\n\n function addGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GUARD_ROLE, _guard);\n emit GuardAdded(_guard);\n }\n\n function removeGuard(address _guard) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GUARD_ROLE, _guard);\n emit GuardRemoved(_guard);\n }\n\n function addGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _grantRole(GOVERNOR_ROLE, _governor);\n emit GovernorAdded(_governor);\n }\n\n function removeGovernor(address _governor) external {\n require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));\n _revokeRole(GOVERNOR_ROLE, _governor);\n emit GovernorRemoved(_governor);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyGovernor {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyGovernor {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyGovernor {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Prove period added to deadline period for proven transactions\n uint256 public constant PROVE_PERIOD = 60 minutes;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check haven't exceeded deadline for prove to happen\n if (block.timestamp \u003e transaction.deadline + PROVE_PERIOD) revert DeadlineExceeded();\n\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRelayer {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyGuard {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // check exceeded deadline for prove to happen\n if (block.timestamp \u003c= transaction.deadline + PROVE_PERIOD) revert DeadlineNotExceeded();\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n ) external {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"37557:2551:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;37557:2551:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"37557:2551:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"UniversalTokenLib\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0xfdd0a71cdd1fe45137a59bc8e7544699eb71ead398af2fd0f1cf448a878ccacd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://07ce767dbb21de80ca0b546310d3c374ed7ddcf5376c7085f15c7812f7678819\",\"dweb:/ipfs/QmQ3JUoivC7YRSxZnRstRKmJJ8x8cLLhEbgWsiXV5NmYrs\"]}},\"version\":1}"},"hashes":{}}} \ No newline at end of file +{"solidity/FastBridgeMock.sol:AccessControl":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n )\n external\n {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Contract module that allows children to implement role-based access control mechanisms. This is a lightweight version that doesn't allow enumerating role members except through off-chain means by accessing the contract event logs. Some applications may benefit from on-chain enumerability, for those cases see {AccessControlEnumerable}. Roles are referred to by their `bytes32` identifier. These should be exposed in the external API and be unique. The best way to achieve this is by using `public constant` hash digests: ```solidity bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\"); ``` Roles can be used to represent a set of permissions. To restrict access to a function call, use {hasRole}: ```solidity function foo() public { require(hasRole(MY_ROLE, msg.sender)); ... } ``` Roles can be granted and revoked dynamically via the {grantRole} and {revokeRole} functions. Each role has an associated admin role, and only accounts that have a role's admin role can call {grantRole} and {revokeRole}. By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using {_setRoleAdmin}. WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} to enforce additional security measures for this role.","errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Contract module that allows children to implement role-based access control mechanisms. This is a lightweight version that doesn't allow enumerating role members except through off-chain means by accessing the contract event logs. Some applications may benefit from on-chain enumerability, for those cases see {AccessControlEnumerable}. Roles are referred to by their `bytes32` identifier. These should be exposed in the external API and be unique. The best way to achieve this is by using `public constant` hash digests: ```solidity bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\"); ``` Roles can be used to represent a set of permissions. To restrict access to a function call, use {hasRole}: ```solidity function foo() public { require(hasRole(MY_ROLE, msg.sender)); ... } ``` Roles can be granted and revoked dynamically via the {grantRole} and {revokeRole} functions. Each role has an associated admin role, and only accounts that have a role's admin role can call {grantRole} and {revokeRole}. By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means that only accounts with this role will be able to grant or revoke other roles. More complex role relationships can be created by using {_setRoleAdmin}. WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to grant and revoke this role. Extra precautions should be taken to secure accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} to enforce additional security measures for this role.\",\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"AccessControl\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0x4fff59c4cd271340f4a824126cbe4ebe7c8dc20639e268edf42ff873af31f862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4d33ef4f98d2abd98b4bbcb403b27495c37843b37000bea9f48e533078144d84\",\"dweb:/ipfs/QmTMkQhtNJPVgpxiLnEG45Ww7xfXHMEoVQ5JdbEbaFXwwS\"]}},\"version\":1}"},"hashes":{"DEFAULT_ADMIN_ROLE()":"a217fddf","getRoleAdmin(bytes32)":"248a9ca3","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","supportsInterface(bytes4)":"01ffc9a7"}},"solidity/FastBridgeMock.sol:AccessControlEnumerable":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n )\n external\n {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Extension of {AccessControl} that allows enumerating the members of each role.","errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"getRoleMember(bytes32,uint256)":{"details":"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information."},"getRoleMemberCount(bytes32)":{"details":"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Extension of {AccessControl} that allows enumerating the members of each role.\",\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"getRoleMember(bytes32,uint256)\":{\"details\":\"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.\"},\"getRoleMemberCount(bytes32)\":{\"details\":\"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"AccessControlEnumerable\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0x4fff59c4cd271340f4a824126cbe4ebe7c8dc20639e268edf42ff873af31f862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4d33ef4f98d2abd98b4bbcb403b27495c37843b37000bea9f48e533078144d84\",\"dweb:/ipfs/QmTMkQhtNJPVgpxiLnEG45Ww7xfXHMEoVQ5JdbEbaFXwwS\"]}},\"version\":1}"},"hashes":{"DEFAULT_ADMIN_ROLE()":"a217fddf","getRoleAdmin(bytes32)":"248a9ca3","getRoleMember(bytes32,uint256)":"9010d07c","getRoleMemberCount(bytes32)":"ca15c873","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","supportsInterface(bytes4)":"01ffc9a7"}},"solidity/FastBridgeMock.sol:Address":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122069309b4b154b9a5a3f92efe9269fb006052caf08cd8c5c5c6db55daf70b3227964736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122069309b4b154b9a5a3f92efe9269fb006052caf08cd8c5c5c6db55daf70b3227964736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n )\n external\n {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"15602:6066:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;15602:6066:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"15602:6066:0:-:0;;;;;;;;","abiDefinition":[{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Collection of functions related to the address type","errors":{"AddressEmptyCode(address)":[{"details":"There's no code at `target` (it is not a contract)."}],"AddressInsufficientBalance(address)":[{"details":"The ETH balance of the account is not enough to perform the operation."}],"FailedInnerCall()":[{"details":"A call to an address target failed. The target may have reverted."}]},"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"}],\"devdoc\":{\"details\":\"Collection of functions related to the address type\",\"errors\":{\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"AddressInsufficientBalance(address)\":[{\"details\":\"The ETH balance of the account is not enough to perform the operation.\"}],\"FailedInnerCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}]},\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"Address\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0x4fff59c4cd271340f4a824126cbe4ebe7c8dc20639e268edf42ff873af31f862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4d33ef4f98d2abd98b4bbcb403b27495c37843b37000bea9f48e533078144d84\",\"dweb:/ipfs/QmTMkQhtNJPVgpxiLnEG45Ww7xfXHMEoVQ5JdbEbaFXwwS\"]}},\"version\":1}"},"hashes":{}},"solidity/FastBridgeMock.sol:Admin":{"code":"0x60806040523480156200001157600080fd5b50604051620014123803806200141283398101604081905262000034916200018e565b6200004160008262000049565b5050620001b9565b60008062000058848462000086565b905080156200007d5760008481526001602052604090206200007b908462000134565b505b90505b92915050565b6000828152602081815260408083206001600160a01b038516845290915281205460ff166200012b576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620000e23390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600162000080565b50600062000080565b60006200007d836001600160a01b03841660008181526001830160205260408120546200012b5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000080565b600060208284031215620001a157600080fd5b81516001600160a01b03811681146200007d57600080fd5b61124980620001c96000396000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806391d14854116100d8578063bf333f2c1161008c578063d547741f11610066578063d547741f14610385578063dcf844a714610398578063e00a83e0146103b857600080fd5b8063bf333f2c14610341578063ca15c8731461034b578063ccc574901461035e57600080fd5b8063a217fddf116100bd578063a217fddf14610313578063b13aa2d61461031b578063b250fe6b1461032e57600080fd5b806391d14854146102a8578063926d7d7f146102ec57600080fd5b80632f2ff15d1161012f57806358f858801161011457806358f85880146102405780635960ccf2146102495780639010d07c1461027057600080fd5b80632f2ff15d1461021a57806336568abe1461022d57600080fd5b806306f333f21161016057806306f333f2146101d95780630f5f6ed7146101ee578063248a9ca3146101f757600080fd5b806301ffc9a71461017c57806303ed0ee5146101a4575b600080fd5b61018f61018a366004611013565b6103c1565b60405190151581526020015b60405180910390f35b6101cb7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b60405190815260200161019b565b6101ec6101e736600461107e565b61041d565b005b6101cb61271081565b6101cb6102053660046110b1565b60009081526020819052604090206001015490565b6101ec6102283660046110ca565b61050b565b6101ec61023b3660046110ca565b610536565b6101cb60025481565b6101cb7fdb9556138406326f00296e13ea2ad7db24ba82381212d816b1a40c23b466b32781565b61028361027e3660046110ed565b61058f565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b61018f6102b63660046110ca565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6101cb7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b6101cb600081565b6101ec6103293660046110b1565b6105ae565b6101ec61033c3660046110b1565b610690565b6101cb620f424081565b6101cb6103593660046110b1565b6106f8565b6101cb7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b6101ec6103933660046110ca565b61070f565b6101cb6103a636600461110f565b60036020526000908152604090205481565b6101cb60045481565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f000000000000000000000000000000000000000000000000000000001480610417575061041782610734565b92915050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55610447816107cb565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120549081900361047b5750505050565b73ffffffffffffffffffffffffffffffffffffffff84166000818152600360205260408120556104ac9084836107d8565b6040805173ffffffffffffffffffffffffffffffffffffffff8087168252851660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b505050565b600082815260208190526040902060010154610526816107cb565b610530838361092f565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610585576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105068282610964565b60008281526001602052604081206105a79083610991565b9392505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556105d8816107cb565b612710821115610649576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064015b60405180910390fd5b600280549083905560408051828152602081018590527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a1505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556106ba816107cb565b600480549083905560408051828152602081018590527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa9101610683565b60008181526001602052604081206104179061099d565b60008281526020819052604090206001015461072a816107cb565b6105308383610964565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061041757507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610417565b6107d581336109a7565b50565b3073ffffffffffffffffffffffffffffffffffffffff8316036107fa57505050565b8060000361080757505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff84160161090e5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461089e576040519150601f19603f3d011682016040523d82523d6000602084013e6108a3565b606091505b5050905080610530576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c6564000000000000000000000000006044820152606401610640565b61050673ffffffffffffffffffffffffffffffffffffffff84168383610a31565b60008061093c8484610abe565b905080156105a757600084815260016020526040902061095c9084610bba565b509392505050565b6000806109718484610bdc565b905080156105a757600084815260016020526040902061095c9084610c97565b60006105a78383610cb9565b6000610417825490565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610a2d576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260248101839052604401610640565b5050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610506908490610ce3565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16610bb25760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610b503390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610417565b506000610417565b60006105a78373ffffffffffffffffffffffffffffffffffffffff8416610d79565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff1615610bb25760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610417565b60006105a78373ffffffffffffffffffffffffffffffffffffffff8416610dc0565b6000826000018281548110610cd057610cd061112a565b9060005260206000200154905092915050565b6000610d0573ffffffffffffffffffffffffffffffffffffffff841683610eb3565b90508051600014158015610d2a575080806020019051810190610d289190611159565b155b15610506576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610640565b6000818152600183016020526040812054610bb257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610417565b60008181526001830160205260408120548015610ea9576000610de460018361117b565b8554909150600090610df89060019061117b565b9050808214610e5d576000866000018281548110610e1857610e1861112a565b9060005260206000200154905080876000018481548110610e3b57610e3b61112a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080610e6e57610e6e6111b5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610417565b6000915050610417565b60606105a783836000846000808573ffffffffffffffffffffffffffffffffffffffff168486604051610ee691906111e4565b60006040518083038185875af1925050503d8060008114610f23576040519150601f19603f3d011682016040523d82523d6000602084013e610f28565b606091505b5091509150610f38868383610f42565b9695505050505050565b606082610f5757610f5282610fd1565b6105a7565b8151158015610f7b575073ffffffffffffffffffffffffffffffffffffffff84163b155b15610fca576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610640565b50806105a7565b805115610fe15780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561102557600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146105a757600080fd5b803573ffffffffffffffffffffffffffffffffffffffff8116811461107957600080fd5b919050565b6000806040838503121561109157600080fd5b61109a83611055565b91506110a860208401611055565b90509250929050565b6000602082840312156110c357600080fd5b5035919050565b600080604083850312156110dd57600080fd5b823591506110a860208401611055565b6000806040838503121561110057600080fd5b50508035926020909101359150565b60006020828403121561112157600080fd5b6105a782611055565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561116b57600080fd5b815180151581146105a757600080fd5b81810381811115610417577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000825160005b8181101561120557602081860181015185830152016111eb565b50600092019182525091905056fea26469706673582212201dd993fc5abfac80cc090826421c56b0e7f52ac1e663c8aeeb7526f35e1246c464736f6c63430008140033","runtime-code":"0x608060405234801561001057600080fd5b50600436106101775760003560e01c806391d14854116100d8578063bf333f2c1161008c578063d547741f11610066578063d547741f14610385578063dcf844a714610398578063e00a83e0146103b857600080fd5b8063bf333f2c14610341578063ca15c8731461034b578063ccc574901461035e57600080fd5b8063a217fddf116100bd578063a217fddf14610313578063b13aa2d61461031b578063b250fe6b1461032e57600080fd5b806391d14854146102a8578063926d7d7f146102ec57600080fd5b80632f2ff15d1161012f57806358f858801161011457806358f85880146102405780635960ccf2146102495780639010d07c1461027057600080fd5b80632f2ff15d1461021a57806336568abe1461022d57600080fd5b806306f333f21161016057806306f333f2146101d95780630f5f6ed7146101ee578063248a9ca3146101f757600080fd5b806301ffc9a71461017c57806303ed0ee5146101a4575b600080fd5b61018f61018a366004611013565b6103c1565b60405190151581526020015b60405180910390f35b6101cb7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b60405190815260200161019b565b6101ec6101e736600461107e565b61041d565b005b6101cb61271081565b6101cb6102053660046110b1565b60009081526020819052604090206001015490565b6101ec6102283660046110ca565b61050b565b6101ec61023b3660046110ca565b610536565b6101cb60025481565b6101cb7fdb9556138406326f00296e13ea2ad7db24ba82381212d816b1a40c23b466b32781565b61028361027e3660046110ed565b61058f565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b61018f6102b63660046110ca565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6101cb7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b6101cb600081565b6101ec6103293660046110b1565b6105ae565b6101ec61033c3660046110b1565b610690565b6101cb620f424081565b6101cb6103593660046110b1565b6106f8565b6101cb7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b6101ec6103933660046110ca565b61070f565b6101cb6103a636600461110f565b60036020526000908152604090205481565b6101cb60045481565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f000000000000000000000000000000000000000000000000000000001480610417575061041782610734565b92915050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55610447816107cb565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120549081900361047b5750505050565b73ffffffffffffffffffffffffffffffffffffffff84166000818152600360205260408120556104ac9084836107d8565b6040805173ffffffffffffffffffffffffffffffffffffffff8087168252851660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b505050565b600082815260208190526040902060010154610526816107cb565b610530838361092f565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610585576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105068282610964565b60008281526001602052604081206105a79083610991565b9392505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556105d8816107cb565b612710821115610649576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064015b60405180910390fd5b600280549083905560408051828152602081018590527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a1505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556106ba816107cb565b600480549083905560408051828152602081018590527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa9101610683565b60008181526001602052604081206104179061099d565b60008281526020819052604090206001015461072a816107cb565b6105308383610964565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061041757507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610417565b6107d581336109a7565b50565b3073ffffffffffffffffffffffffffffffffffffffff8316036107fa57505050565b8060000361080757505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff84160161090e5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461089e576040519150601f19603f3d011682016040523d82523d6000602084013e6108a3565b606091505b5050905080610530576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c6564000000000000000000000000006044820152606401610640565b61050673ffffffffffffffffffffffffffffffffffffffff84168383610a31565b60008061093c8484610abe565b905080156105a757600084815260016020526040902061095c9084610bba565b509392505050565b6000806109718484610bdc565b905080156105a757600084815260016020526040902061095c9084610c97565b60006105a78383610cb9565b6000610417825490565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610a2d576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260248101839052604401610640565b5050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610506908490610ce3565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16610bb25760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610b503390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610417565b506000610417565b60006105a78373ffffffffffffffffffffffffffffffffffffffff8416610d79565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff1615610bb25760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610417565b60006105a78373ffffffffffffffffffffffffffffffffffffffff8416610dc0565b6000826000018281548110610cd057610cd061112a565b9060005260206000200154905092915050565b6000610d0573ffffffffffffffffffffffffffffffffffffffff841683610eb3565b90508051600014158015610d2a575080806020019051810190610d289190611159565b155b15610506576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610640565b6000818152600183016020526040812054610bb257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610417565b60008181526001830160205260408120548015610ea9576000610de460018361117b565b8554909150600090610df89060019061117b565b9050808214610e5d576000866000018281548110610e1857610e1861112a565b9060005260206000200154905080876000018481548110610e3b57610e3b61112a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080610e6e57610e6e6111b5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610417565b6000915050610417565b60606105a783836000846000808573ffffffffffffffffffffffffffffffffffffffff168486604051610ee691906111e4565b60006040518083038185875af1925050503d8060008114610f23576040519150601f19603f3d011682016040523d82523d6000602084013e610f28565b606091505b5091509150610f38868383610f42565b9695505050505050565b606082610f5757610f5282610fd1565b6105a7565b8151158015610f7b575073ffffffffffffffffffffffffffffffffffffffff84163b155b15610fca576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610640565b50806105a7565b805115610fe15780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561102557600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146105a757600080fd5b803573ffffffffffffffffffffffffffffffffffffffff8116811461107957600080fd5b919050565b6000806040838503121561109157600080fd5b61109a83611055565b91506110a860208401611055565b90509250929050565b6000602082840312156110c357600080fd5b5035919050565b600080604083850312156110dd57600080fd5b823591506110a860208401611055565b6000806040838503121561110057600080fd5b50508035926020909101359150565b60006020828403121561112157600080fd5b6105a782611055565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561116b57600080fd5b815180151581146105a757600080fd5b81810381811115610417577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000825160005b8181101561120557602081860181015185830152016111eb565b50600092019182525091905056fea26469706673582212201dd993fc5abfac80cc090826421c56b0e7f52ac1e663c8aeeb7526f35e1246c464736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n )\n external\n {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"56331:1843:0:-:0;;;57158:83;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;57196:38;46368:4;57227:6;57196:10;:38::i;:::-;;57158:83;56331:1843;;55681:257;55767:4;;55798:31;55815:4;55821:7;55798:16;:31::i;:::-;55783:46;;55843:7;55839:69;;;55866:18;;;;:12;:18;;;;;:31;;55889:7;55866:22;:31::i;:::-;;55839:69;55924:7;-1:-1:-1;55681:257:0;;;;;:::o;50315:316::-;50392:4;47090:12;;;;;;;;;;;-1:-1:-1;;;;;47090:29:0;;;;;;;;;;;;50408:217;;50451:6;:12;;;;;;;;;;;-1:-1:-1;;;;;50451:29:0;;;;;;;;;:36;;-1:-1:-1;;50451:36:0;50483:4;50451:36;;;50533:12;22406:10;;22327:96;50533:12;-1:-1:-1;;;;;50506:40:0;50524:7;-1:-1:-1;;;;;50506:40:0;50518:4;50506:40;;;;;;;;;;-1:-1:-1;50567:4:0;50560:11;;50408:217;-1:-1:-1;50609:5:0;50602:12;;31852:150;31922:4;31945:50;31950:3;-1:-1:-1;;;;;31970:23:0;;25840:4;27896:21;;;:14;;;:21;;;;;;25856:321;;-1:-1:-1;25898:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;26080:18;;26056:21;;;:14;;;:21;;;;;;:42;;;;26112:11;;14:290:1;84:6;137:2;125:9;116:7;112:23;108:32;105:52;;;153:1;150;143:12;105:52;179:16;;-1:-1:-1;;;;;224:31:1;;214:42;;204:70;;270:1;267;260:12;14:290;56331:1843:0;;;;;;","srcMapRuntime":"56331:1843:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54341:212;;;;;;:::i;:::-;;:::i;:::-;;;516:14:1;;509:22;491:41;;479:2;464:18;54341:212:0;;;;;;;;56571:60;;56608:23;56571:60;;;;;689:25:1;;;677:2;662:18;56571:60:0;543:177:1;57543:359:0;;;;;;:::i;:::-;;:::i;:::-;;56753:45;;56792:6;56753:45;;47946:120;;;;;;:::i;:::-;48011:7;48037:12;;;;;;;;;;:22;;;;47946:120;48362:136;;;;;;:::i;:::-;;:::i;49464:245::-;;;;;;:::i;:::-;;:::i;56915:30::-;;;;;;56499:66;;56539:26;56499:66;;55138:142;;;;;;:::i;:::-;;:::i;:::-;;;2246:42:1;2234:55;;;2216:74;;2204:2;2189:18;55138:142:0;2070:226:1;46990:136:0;;;;;;:::i;:::-;47067:4;47090:12;;;;;;;;;;;:29;;;;;;;;;;;;;;;;46990:136;56429:64;;56468:25;56429:64;;46323:49;;46368:4;46323:49;;57247:290;;;;;;:::i;:::-;;:::i;57908:264::-;;;;;;:::i;:::-;;:::i;56710:37::-;;56744:3;56710:37;;55448:131;;;;;;:::i;:::-;;:::i;56637:66::-;;56677:26;56637:66;;48778:138;;;;;;:::i;:::-;;:::i;57001:47::-;;;;;;:::i;:::-;;;;;;;;;;;;;;57122:29;;;;;;54341:212;54426:4;54449:57;;;54464:42;54449:57;;:97;;;54510:36;54534:11;54510:23;:36::i;:::-;54442:104;54341:212;-1:-1:-1;;54341:212:0:o;57543:359::-;56677:26;46600:16;46611:4;46600:10;:16::i;:::-;57667:19:::1;::::0;::::1;57647:17;57667:19:::0;;;:12:::1;:19;::::0;;;;;;57700:14;;;57696:27:::1;;57716:7;57543:359:::0;;;:::o;57696:27::-:1;57764:19;::::0;::::1;57786:1;57764:19:::0;;;:12:::1;:19;::::0;;;;:23;57797:45:::1;::::0;57821:9;57832;57797:23:::1;:45::i;:::-;57857:38;::::0;;2889:42:1;2958:15;;;2940:34;;3010:15;;3005:2;2990:18;;2983:43;3042:18;;;3035:34;;;57857:38:0::1;::::0;2867:2:1;2852:18;57857:38:0::1;;;;;;;57637:265;46626:1;57543:359:::0;;;:::o;48362:136::-;48011:7;48037:12;;;;;;;;;;:22;;;46600:16;46611:4;46600:10;:16::i;:::-;48466:25:::1;48477:4;48483:7;48466:10;:25::i;:::-;;48362:136:::0;;;:::o;49464:245::-;49557:34;;;22406:10;49557:34;49553:102;;49614:30;;;;;;;;;;;;;;49553:102;49665:37;49677:4;49683:18;49665:11;:37::i;55138:142::-;55219:7;55245:18;;;:12;:18;;;;;:28;;55267:5;55245:21;:28::i;:::-;55238:35;55138:142;-1:-1:-1;;;55138:142:0:o;57247:290::-;56677:26;46600:16;46611:4;46600:10;:16::i;:::-;56792:6:::1;57346:10;:26;;57338:55;;;::::0;::::1;::::0;;3282:2:1;57338:55:0::1;::::0;::::1;3264:21:1::0;3321:2;3301:18;;;3294:30;3360:18;3340;;;3333:46;3396:18;;57338:55:0::1;;;;;;;;;57424:15;::::0;;57449:28;;;;57492:38:::1;::::0;;3599:25:1;;;3655:2;3640:18;;3633:34;;;57492:38:0::1;::::0;3572:18:1;57492:38:0::1;;;;;;;;57328:209;57247:290:::0;;:::o;57908:264::-;56677:26;46600:16;46611:4;46600:10;:16::i;:::-;58033:14:::1;::::0;;58057:34;;;;58106:59:::1;::::0;;3599:25:1;;;3655:2;3640:18;;3633:34;;;58106:59:0::1;::::0;3572:18:1;58106:59:0::1;3425:248:1::0;55448:131:0;55519:7;55545:18;;;:12;:18;;;;;:27;;:25;:27::i;48778:138::-;48011:7;48037:12;;;;;;;;;;:22;;;46600:16;46611:4;46600:10;:16::i;:::-;48883:26:::1;48895:4;48901:7;48883:11;:26::i;46701:202::-:0;46786:4;46809:47;;;46824:32;46809:47;;:87;;-1:-1:-1;38614:25:0;38599:40;;;;46860:36;38500:146;47335:103;47401:30;47412:4;22406:10;47401;:30::i;:::-;47335:103;:::o;51613:653::-;51788:4;51774:19;;;;51770:32;;51613:653;;;:::o;51770:32::-;51874:5;51883:1;51874:10;51870:23;;51613:653;;;:::o;51870:23::-;51906:20;;;;;51902:358;;52086:12;52103:2;:7;;52118:5;52103:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52085:43;;;52150:7;52142:39;;;;;;;4090:2:1;52142:39:0;;;4072:21:1;4129:2;4109:18;;;4102:30;4168:21;4148:18;;;4141:49;4207:18;;52142:39:0;3888:343:1;51902:358:0;52212:37;:26;;;52239:2;52243:5;52212:26;:37::i;55681:257::-;55767:4;55783:12;55798:31;55815:4;55821:7;55798:16;:31::i;:::-;55783:46;;55843:7;55839:69;;;55866:18;;;;:12;:18;;;;;:31;;55889:7;55866:22;:31::i;:::-;;55924:7;55681:257;-1:-1:-1;;;55681:257:0:o;56041:262::-;56128:4;56144:12;56159:32;56177:4;56183:7;56159:17;:32::i;:::-;56144:47;;56205:7;56201:72;;;56228:18;;;;:12;:18;;;;;:34;;56254:7;56228:25;:34::i;33110:156::-;33184:7;33234:22;33238:3;33250:5;33234:3;:22::i;32653:115::-;32716:7;32742:19;32750:3;28092:18;;28010:107;47568:197;47067:4;47090:12;;;;;;;;;;;:29;;;;;;;;;;;;;47651:108;;47701:47;;;;;4440:42:1;4428:55;;47701:47:0;;;4410:74:1;4500:18;;;4493:34;;;4383:18;;47701:47:0;4236:297:1;47651:108:0;47568:197;;:::o;39818:160::-;39927:43;;;39942:14;4428:55:1;;39927:43:0;;;4410:74:1;4500:18;;;;4493:34;;;39927:43:0;;;;;;;;;;4383:18:1;;;;39927:43:0;;;;;;;;;;;;;;39900:71;;39920:5;;39900:19;:71::i;50315:316::-;50392:4;47090:12;;;;;;;;;;;:29;;;;;;;;;;;;;50408:217;;50451:6;:12;;;;;;;;;;;:29;;;;;;;;;;:36;;;;50483:4;50451:36;;;50533:12;22406:10;;22327:96;50533:12;50506:40;;50524:7;50506:40;;50518:4;50506:40;;;;;;;;;;-1:-1:-1;50567:4:0;50560:11;;50408:217;-1:-1:-1;50609:5:0;50602:12;;31852:150;31922:4;31945:50;31950:3;31970:23;;;31945:4;:50::i;50866:317::-;50944:4;47090:12;;;;;;;;;;;:29;;;;;;;;;;;;;50960:217;;;51034:5;51002:12;;;;;;;;;;;:29;;;;;;;;;;;:37;;;;;;51058:40;22406:10;;51002:12;;51058:40;;51034:5;51058:40;-1:-1:-1;51119:4:0;51112:11;;32170:156;32243:4;32266:53;32274:3;32294:23;;;32266:7;:53::i;28459:118::-;28526:7;28552:3;:11;;28564:5;28552:18;;;;;;;;:::i;:::-;;;;;;;;;28545:25;;28459:118;;;;:::o;42574:629::-;42993:23;43019:33;:27;;;43047:4;43019:27;:33::i;:::-;42993:59;;43066:10;:17;43087:1;43066:22;;:57;;;;;43104:10;43093:30;;;;;;;;;;;;:::i;:::-;43092:31;43066:57;43062:135;;;43146:40;;;;;2246:42:1;2234:55;;43146:40:0;;;2216:74:1;2189:18;;43146:40:0;2070:226:1;25777:406:0;25840:4;27896:21;;;:14;;;:21;;;;;;25856:321;;-1:-1:-1;25898:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;26080:18;;26056:21;;;:14;;;:21;;;;;;:42;;;;26112:11;;26351:1368;26417:4;26546:21;;;:14;;;:21;;;;;;26582:13;;26578:1135;;26949:18;26970:12;26981:1;26970:8;:12;:::i;:::-;27016:18;;26949:33;;-1:-1:-1;26996:17:0;;27016:22;;27037:1;;27016:22;:::i;:::-;26996:42;;27071:9;27057:10;:23;27053:378;;27100:17;27120:3;:11;;27132:9;27120:22;;;;;;;;:::i;:::-;;;;;;;;;27100:42;;27267:9;27241:3;:11;;27253:10;27241:23;;;;;;;;:::i;:::-;;;;;;;;;;;;:35;;;;27380:25;;;:14;;;:25;;;;;:36;;;27053:378;27509:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;27612:3;:14;;:21;27627:5;27612:21;;;;;;;;;;;27605:28;;;27655:4;27648:11;;;;;;;26578:1135;27697:5;27690:12;;;;;18112:151;18187:12;18218:38;18240:6;18248:4;18254:1;18187:12;18828;18842:23;18869:6;:11;;18888:5;18895:4;18869:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18827:73;;;;18917:55;18944:6;18952:7;18961:10;18917:26;:55::i;:::-;18910:62;18587:392;-1:-1:-1;;;;;;18587:392:0:o;20032:582::-;20176:12;20205:7;20200:408;;20228:19;20236:10;20228:7;:19::i;:::-;20200:408;;;20452:17;;:22;:49;;;;-1:-1:-1;20478:18:0;;;;:23;20452:49;20448:119;;;20528:24;;;;;2246:42:1;2234:55;;20528:24:0;;;2216:74:1;2189:18;;20528:24:0;2070:226:1;20448:119:0;-1:-1:-1;20587:10:0;20580:17;;21150:516;21281:17;;:21;21277:383;;21509:10;21503:17;21565:15;21552:10;21548:2;21544:19;21537:44;21277:383;21632:17;;;;;;;;;;;;;;14:332:1;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;180:9;167:23;230:66;223:5;219:78;212:5;209:89;199:117;;312:1;309;302:12;725:196;793:20;;853:42;842:54;;832:65;;822:93;;911:1;908;901:12;822:93;725:196;;;:::o;926:260::-;994:6;1002;1055:2;1043:9;1034:7;1030:23;1026:32;1023:52;;;1071:1;1068;1061:12;1023:52;1094:29;1113:9;1094:29;:::i;:::-;1084:39;;1142:38;1176:2;1165:9;1161:18;1142:38;:::i;:::-;1132:48;;926:260;;;;;:::o;1373:180::-;1432:6;1485:2;1473:9;1464:7;1460:23;1456:32;1453:52;;;1501:1;1498;1491:12;1453:52;-1:-1:-1;1524:23:1;;1373:180;-1:-1:-1;1373:180:1:o;1558:254::-;1626:6;1634;1687:2;1675:9;1666:7;1662:23;1658:32;1655:52;;;1703:1;1700;1693:12;1655:52;1739:9;1726:23;1716:33;;1768:38;1802:2;1791:9;1787:18;1768:38;:::i;1817:248::-;1885:6;1893;1946:2;1934:9;1925:7;1921:23;1917:32;1914:52;;;1962:1;1959;1952:12;1914:52;-1:-1:-1;;1985:23:1;;;2055:2;2040:18;;;2027:32;;-1:-1:-1;1817:248:1:o;2486:186::-;2545:6;2598:2;2586:9;2577:7;2573:23;2569:32;2566:52;;;2614:1;2611;2604:12;2566:52;2637:29;2656:9;2637:29;:::i;4840:184::-;4892:77;4889:1;4882:88;4989:4;4986:1;4979:15;5013:4;5010:1;5003:15;5029:277;5096:6;5149:2;5137:9;5128:7;5124:23;5120:32;5117:52;;;5165:1;5162;5155:12;5117:52;5197:9;5191:16;5250:5;5243:13;5236:21;5229:5;5226:32;5216:60;;5272:1;5269;5262:12;5311:282;5378:9;;;5399:11;;;5396:191;;;5443:77;5440:1;5433:88;5544:4;5541:1;5534:15;5572:4;5569:1;5562:15;5598:184;5650:77;5647:1;5640:88;5747:4;5744:1;5737:15;5771:4;5768:1;5761:15;5787:412;5916:3;5954:6;5948:13;5979:1;5989:129;6003:6;6000:1;5997:13;5989:129;;;6101:4;6085:14;;;6081:25;;6075:32;6062:11;;;6055:53;6018:12;5989:129;;;-1:-1:-1;6173:1:1;6137:16;;6162:13;;;-1:-1:-1;6137:16:1;5787:412;-1:-1:-1;5787:412:1:o","abiDefinition":[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldChainGasAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"ChainGasAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFeeRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"FeeRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesSwept","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_RATE_MAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GOVERNOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GUARD_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFUNDER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAYER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainGasAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"protocolFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"setChainGasAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"setProtocolFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"sweepProtocolFees","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"chainGasAmount()":{"notice":"Chain gas amount to forward as rebate if requested"},"protocolFeeRate()":{"notice":"Protocol fee rate taken on origin amount deposited in origin chain"},"protocolFees(address)":{"notice":"Protocol fee amounts accumulated"}},"version":1},"developerDoc":{"errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}],"AddressEmptyCode(address)":[{"details":"There's no code at `target` (it is not a contract)."}],"AddressInsufficientBalance(address)":[{"details":"The ETH balance of the account is not enough to perform the operation."}],"FailedInnerCall()":[{"details":"A call to an address target failed. The target may have reverted."}],"SafeERC20FailedOperation(address)":[{"details":"An operation with an ERC-20 token failed."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"getRoleMember(bytes32,uint256)":{"details":"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information."},"getRoleMemberCount(bytes32)":{"details":"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REFUNDER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}],\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"AddressInsufficientBalance(address)\":[{\"details\":\"The ETH balance of the account is not enough to perform the operation.\"}],\"FailedInnerCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"getRoleMember(bytes32,uint256)\":{\"details\":\"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.\"},\"getRoleMemberCount(bytes32)\":{\"details\":\"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"chainGasAmount()\":{\"notice\":\"Chain gas amount to forward as rebate if requested\"},\"protocolFeeRate()\":{\"notice\":\"Protocol fee rate taken on origin amount deposited in origin chain\"},\"protocolFees(address)\":{\"notice\":\"Protocol fee amounts accumulated\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"Admin\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0x4fff59c4cd271340f4a824126cbe4ebe7c8dc20639e268edf42ff873af31f862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4d33ef4f98d2abd98b4bbcb403b27495c37843b37000bea9f48e533078144d84\",\"dweb:/ipfs/QmTMkQhtNJPVgpxiLnEG45Ww7xfXHMEoVQ5JdbEbaFXwwS\"]}},\"version\":1}"},"hashes":{"DEFAULT_ADMIN_ROLE()":"a217fddf","FEE_BPS()":"bf333f2c","FEE_RATE_MAX()":"0f5f6ed7","GOVERNOR_ROLE()":"ccc57490","GUARD_ROLE()":"03ed0ee5","REFUNDER_ROLE()":"5960ccf2","RELAYER_ROLE()":"926d7d7f","chainGasAmount()":"e00a83e0","getRoleAdmin(bytes32)":"248a9ca3","getRoleMember(bytes32,uint256)":"9010d07c","getRoleMemberCount(bytes32)":"ca15c873","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","protocolFeeRate()":"58f85880","protocolFees(address)":"dcf844a7","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","setChainGasAmount(uint256)":"b250fe6b","setProtocolFeeRate(uint256)":"b13aa2d6","supportsInterface(bytes4)":"01ffc9a7","sweepProtocolFees(address,address)":"06f333f2"}},"solidity/FastBridgeMock.sol:Context":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n )\n external\n {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.","kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"details\":\"Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"Context\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0x4fff59c4cd271340f4a824126cbe4ebe7c8dc20639e268edf42ff873af31f862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4d33ef4f98d2abd98b4bbcb403b27495c37843b37000bea9f48e533078144d84\",\"dweb:/ipfs/QmTMkQhtNJPVgpxiLnEG45Ww7xfXHMEoVQ5JdbEbaFXwwS\"]}},\"version\":1}"},"hashes":{}},"solidity/FastBridgeMock.sol:ERC165":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n )\n external\n {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Implementation of the {IERC165} interface. Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check for the additional interface id that will be supported. For example: ```solidity function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); } ```","kind":"dev","methods":{"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Implementation of the {IERC165} interface. Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check for the additional interface id that will be supported. For example: ```solidity function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); } ```\",\"kind\":\"dev\",\"methods\":{\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"ERC165\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0x4fff59c4cd271340f4a824126cbe4ebe7c8dc20639e268edf42ff873af31f862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4d33ef4f98d2abd98b4bbcb403b27495c37843b37000bea9f48e533078144d84\",\"dweb:/ipfs/QmTMkQhtNJPVgpxiLnEG45Ww7xfXHMEoVQ5JdbEbaFXwwS\"]}},\"version\":1}"},"hashes":{"supportsInterface(bytes4)":"01ffc9a7"}},"solidity/FastBridgeMock.sol:EnumerableSet":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212200d8618a82dfc0c2e00136a6baf933d53111fd9bd0c5433b637ac80498bb32ba464736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212200d8618a82dfc0c2e00136a6baf933d53111fd9bd0c5433b637ac80498bb32ba464736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n )\n external\n {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"24866:11640:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;24866:11640:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"24866:11640:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Library for managing https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive types. Sets have the following properties: - Elements are added, removed, and checked for existence in constant time (O(1)). - Elements are enumerated in O(n). No guarantees are made on the ordering. ```solidity contract Example { // Add the library methods using EnumerableSet for EnumerableSet.AddressSet; // Declare a set state variable EnumerableSet.AddressSet private mySet; } ``` As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) and `uint256` (`UintSet`) are supported. [WARNING] ==== Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. ====","kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"details\":\"Library for managing https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive types. Sets have the following properties: - Elements are added, removed, and checked for existence in constant time (O(1)). - Elements are enumerated in O(n). No guarantees are made on the ordering. ```solidity contract Example { // Add the library methods using EnumerableSet for EnumerableSet.AddressSet; // Declare a set state variable EnumerableSet.AddressSet private mySet; } ``` As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) and `uint256` (`UintSet`) are supported. [WARNING] ==== Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. ====\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"EnumerableSet\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0x4fff59c4cd271340f4a824126cbe4ebe7c8dc20639e268edf42ff873af31f862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4d33ef4f98d2abd98b4bbcb403b27495c37843b37000bea9f48e533078144d84\",\"dweb:/ipfs/QmTMkQhtNJPVgpxiLnEG45Ww7xfXHMEoVQ5JdbEbaFXwwS\"]}},\"version\":1}"},"hashes":{}},"solidity/FastBridgeMock.sol:FastBridge":{"code":"0x60a06040523480156200001157600080fd5b5060405162002d7a38038062002d7a833981016040819052620000349162000194565b80620000426000826200004f565b50504360805250620001bf565b6000806200005e84846200008c565b90508015620000835760008481526001602052604090206200008190846200013a565b505b90505b92915050565b6000828152602081815260408083206001600160a01b038516845290915281205460ff1662000131576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620000e83390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600162000086565b50600062000086565b600062000083836001600160a01b0384166000818152600183016020526040812054620001315750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000086565b600060208284031215620001a757600080fd5b81516001600160a01b03811681146200008357600080fd5b608051612b9f620001db60003960006106510152612b9f6000f3fe60806040526004361061026a5760003560e01c80639010d07c11610153578063add98c70116100cb578063ca15c8731161007f578063d547741f11610064578063d547741f146107a1578063dcf844a7146107c1578063e00a83e0146107ee57600080fd5b8063ca15c8731461074d578063ccc574901461076d57600080fd5b8063b13aa2d6116100b0578063b13aa2d6146106f6578063b250fe6b14610716578063bf333f2c1461073657600080fd5b8063add98c70146106c0578063affed0e0146106e057600080fd5b8063a217fddf11610122578063a5bbe22b11610107578063a5bbe22b1461047f578063aa9641ab14610673578063ac11fb1a1461069357600080fd5b8063a217fddf1461062a578063a3ec191a1461063f57600080fd5b80639010d07c146104f857806391ad50391461053057806391d14854146105b2578063926d7d7f146105f657600080fd5b806341fcb612116101e65780635eb7d946116101b55780638379a24f1161019a5780638379a24f14610495578063886d36ff146104c55780638f0d6f17146104e557600080fd5b80635eb7d9461461045f578063820688d51461047f57600080fd5b806341fcb612146103e2578063458516941461040257806358f85880146104155780635960ccf21461042b57600080fd5b80630f5f6ed71161023d578063248a9ca311610222578063248a9ca3146103725780632f2ff15d146103a257806336568abe146103c257600080fd5b80630f5f6ed714610345578063190da5951461035b57600080fd5b806301ffc9a71461026f57806303ed0ee5146102a4578063051287bc146102e657806306f333f214610323575b600080fd5b34801561027b57600080fd5b5061028f61028a3660046122fc565b610804565b60405190151581526020015b60405180910390f35b3480156102b057600080fd5b506102d87f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b60405190815260200161029b565b3480156102f257600080fd5b5061031661030136600461233e565b60056020526000908152604090205460ff1681565b60405161029b9190612386565b34801561032f57600080fd5b5061034361033e3660046123ec565b610860565b005b34801561035157600080fd5b506102d861271081565b34801561036757600080fd5b506102d862093a8081565b34801561037e57600080fd5b506102d861038d36600461233e565b60009081526020819052604090206001015490565b3480156103ae57600080fd5b506103436103bd366004612425565b610927565b3480156103ce57600080fd5b506103436103dd366004612425565b610952565b3480156103ee57600080fd5b506103436103fd366004612572565b61099e565b6103436104103660046125ef565b610bd7565b34801561042157600080fd5b506102d860025481565b34801561043757600080fd5b506102d87fdb9556138406326f00296e13ea2ad7db24ba82381212d816b1a40c23b466b32781565b34801561046b57600080fd5b5061034361047a366004612692565b610ee5565b34801561048b57600080fd5b506102d861070881565b3480156104a157600080fd5b5061028f6104b036600461233e565b60076020526000908152604090205460ff1681565b3480156104d157600080fd5b506103436104e03660046126cf565b6110bd565b6103436104f3366004612692565b6111f0565b34801561050457600080fd5b50610518610513366004612714565b611437565b6040516001600160a01b03909116815260200161029b565b34801561053c57600080fd5b5061058661054b36600461233e565b6006602052600090815260409020546bffffffffffffffffffffffff8116906c0100000000000000000000000090046001600160a01b031682565b604080516bffffffffffffffffffffffff90931683526001600160a01b0390911660208301520161029b565b3480156105be57600080fd5b5061028f6105cd366004612425565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561060257600080fd5b506102d87fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b34801561063657600080fd5b506102d8600081565b34801561064b57600080fd5b506102d87f000000000000000000000000000000000000000000000000000000000000000081565b34801561067f57600080fd5b5061028f61068e366004612425565b611456565b34801561069f57600080fd5b506106b36106ae366004612692565b611559565b60405161029b9190612736565b3480156106cc57600080fd5b506103436106db36600461233e565b6115cc565b3480156106ec57600080fd5b506102d860085481565b34801561070257600080fd5b5061034361071136600461233e565b611735565b34801561072257600080fd5b5061034361073136600461233e565b611817565b34801561074257600080fd5b506102d8620f424081565b34801561075957600080fd5b506102d861076836600461233e565b61187f565b34801561077957600080fd5b506102d87f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b3480156107ad57600080fd5b506103436107bc366004612425565b611896565b3480156107cd57600080fd5b506102d86107dc36600461281c565b60036020526000908152604090205481565b3480156107fa57600080fd5b506102d860045481565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f00000000000000000000000000000000000000000000000000000000148061085a575061085a826118bb565b92915050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561088a81611952565b6001600160a01b038316600090815260036020526040812054908190036108b15750505050565b6001600160a01b0384166000818152600360205260408120556108d590848361195f565b604080516001600160a01b038087168252851660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b505050565b60008281526020819052604090206001015461094281611952565b61094c8383611a82565b50505050565b6001600160a01b0381163314610994576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109228282611ab7565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc46109c881611952565b8251602084012060006109da85611559565b9050600260008381526005602052604090205460ff166004811115610a0157610a01612357565b14610a38576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660209081526040918290208251808401909352546bffffffffffffffffffffffff811683526c0100000000000000000000000090046001600160a01b03169082018190523314610abb576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611610b08576040517f1992d0bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600560205260409020805460ff1916600317905561010082015115610b645761010082015160808301516001600160a01b031660009081526003602052604081208054909190610b5e908490612868565b90915550505b608082015160c0830151610b826001600160a01b038316888361195f565b604080516001600160a01b03848116825260208201849052891691339188917f582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac67891015b60405180910390a45050505050505050565b46816000015163ffffffff1603610c1a576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a08101511580610c2d575060c0810151155b15610c64576040517fe38820c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608101516001600160a01b03161580610c89575060808101516001600160a01b0316155b15610cc0576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ccc61070842612868565b8161010001511015610d0a576040517f04b7fcc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d1f3083606001518460a00151611ae4565b90506000806002541115610d4c57620f424060025483610d3f919061287b565b610d499190612892565b90505b610d5681836128cd565b915060006040518061018001604052804663ffffffff168152602001856000015163ffffffff16815260200185602001516001600160a01b0316815260200185604001516001600160a01b0316815260200185606001516001600160a01b0316815260200185608001516001600160a01b031681526020018481526020018560c0015181526020018381526020018560e0015115158152602001856101000151815260200160086000815480929190610e0e906128e0565b909155509052604051610e249190602001612736565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152828252805160208083019190912060008181526005835293909320805460ff191660011790558701518751606089015160808a015160c08b015160e08c015195985095966001600160a01b039094169587957f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a95610ed6958b959094909390928e9261293c565b60405180910390a35050505050565b805160208201206000610ef783611559565b3360009081527fd2043bf65931af3dbecf60d0db8f40e4160406d7beb00522f4200cf4944a1eb8602052604090205490915060ff1615610f74578061014001514211610f6f576040517fe15ff9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fc0565b62093a80816101400151610f889190612868565b4211610fc0576040517fe15ff9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008381526005602052604090205460ff166004811115610fe557610fe5612357565b1461101c576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260056020526040808220805460ff19166004179055820151608083015161010084015160c0850151929391926110579190612868565b905061106d6001600160a01b038316848361195f565b604080516001600160a01b0384811682526020820184905285169187917fb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958910160405180910390a3505050505050565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc46110e781611952565b82516020840120600160008281526005602052604090205460ff16600481111561111357611113612357565b1461114a576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526005602090815260408083208054600260ff19909116179055805180820182526bffffffffffffffffffffffff4281168252338285018181528787526006865295849020925195516001600160a01b03166c0100000000000000000000000002959091169490941790555185815283917f4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4910160405180910390a350505050565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc461121a81611952565b81516020830120600061122c84611559565b90504663ffffffff16816020015163ffffffff1614611277576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8061014001514211156112b6576040517f559895a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526007602052604090205460ff16156112ff576040517fbef7bb7d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600760205260409020805460ff19166001179055606081015160a082015160e083015160045461012085015161134857506000611342848484611ae4565b506113b9565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b0384160161138c5761134284846113878486612868565b611ae4565b611397848484611ae4565b506113b78473eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee83611ae4565b505b845160808087015160a08089015160c0808b015160e08c01516040805163ffffffff90991689526001600160a01b0396871660208a0152938616938801939093526060870152938501528301849052861691339189917ff8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c9101610bc5565b600082815260016020526040812061144f9083611cb3565b9392505050565b6000600260008481526005602052604090205460ff16600481111561147d5761147d612357565b146114b4576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600660209081526040918290208251808401909352546bffffffffffffffffffffffff811683526001600160a01b036c01000000000000000000000000909104811691830182905284161461153a576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611949350505050565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201528251909161085a91840181019084016129ed565b7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d6115f681611952565b600260008381526005602052604090205460ff16600481111561161b5761161b612357565b14611652576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660209081526040918290208251808401909352546bffffffffffffffffffffffff8082168085526c010000000000000000000000009092046001600160a01b031693909201929092526107089142031611156116e1576040517f3e908aac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040808320805460ff19166001179055600690915280822082905551339184917f0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad49190a35050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561175f81611952565b6127108211156117d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064015b60405180910390fd5b600280549083905560408051828152602081018590527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a1505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561184181611952565b600480549083905560408051828152602081018590527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa910161180a565b600081815260016020526040812061085a90611cbf565b6000828152602081905260409020600101546118b181611952565b61094c8383611ab7565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061085a57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461085a565b61195c8133611cc9565b50565b306001600160a01b0383160361197457505050565b8060000361198157505050565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03841601611a6e576000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146119fe576040519150601f19603f3d011682016040523d82523d6000602084013e611a03565b606091505b505090508061094c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c65640000000000000000000000000060448201526064016117c7565b6109226001600160a01b0384168383611d39565b600080611a8f8484611dad565b9050801561144f576000848152600160205260409020611aaf9084611e57565b509392505050565b600080611ac48484611e6c565b9050801561144f576000848152600160205260409020611aaf9084611eef565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611c4d57611b1c836001600160a01b0316611f04565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528416906370a0823190602401602060405180830381865afa158015611b7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9f9190612ab9565b9050611bb66001600160a01b038416338685611faa565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528291908516906370a0823190602401602060405180830381865afa158015611c18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c3c9190612ab9565b611c4691906128cd565b905061144f565b348214611c86576040517f81de0bf300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0384163014611caa57611caa6001600160a01b038416858461195f565b50349392505050565b600061144f8383611fe3565b600061085a825490565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16611d35576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602481018390526044016117c7565b5050565b6040516001600160a01b0383811660248301526044820183905261092291859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061200d565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16611e4f576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055611e073390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161085a565b50600061085a565b600061144f836001600160a01b038416612089565b6000828152602081815260408083206001600160a01b038516845290915281205460ff1615611e4f576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161085a565b600061144f836001600160a01b0384166120d0565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03821601611f66576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03163b60000361195c576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b03848116602483015283811660448301526064820183905261094c9186918216906323b872dd90608401611d66565b6000826000018281548110611ffa57611ffa612ad2565b9060005260206000200154905092915050565b60006120226001600160a01b038416836121c3565b905080516000141580156120475750808060200190518101906120459190612b01565b155b15610922576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024016117c7565b6000818152600183016020526040812054611e4f5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561085a565b600081815260018301602052604081205480156121b95760006120f46001836128cd565b8554909150600090612108906001906128cd565b905080821461216d57600086600001828154811061212857612128612ad2565b906000526020600020015490508087600001848154811061214b5761214b612ad2565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061217e5761217e612b1e565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061085a565b600091505061085a565b606061144f8383600084600080856001600160a01b031684866040516121e99190612b4d565b60006040518083038185875af1925050503d8060008114612226576040519150601f19603f3d011682016040523d82523d6000602084013e61222b565b606091505b509150915061223b868383612245565b9695505050505050565b60608261225a57612255826122ba565b61144f565b815115801561227157506001600160a01b0384163b155b156122b3576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016117c7565b508061144f565b8051156122ca5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561230e57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461144f57600080fd5b60006020828403121561235057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600583106123c1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6001600160a01b038116811461195c57600080fd5b80356123e7816123c7565b919050565b600080604083850312156123ff57600080fd5b823561240a816123c7565b9150602083013561241a816123c7565b809150509250929050565b6000806040838503121561243857600080fd5b82359150602083013561241a816123c7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171561249d5761249d61244a565b60405290565b604051610180810167ffffffffffffffff8111828210171561249d5761249d61244a565b600082601f8301126124d857600080fd5b813567ffffffffffffffff808211156124f3576124f361244a565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156125395761253961244a565b8160405283815286602085880101111561255257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806040838503121561258557600080fd5b823567ffffffffffffffff81111561259c57600080fd5b6125a8858286016124c7565b925050602083013561241a816123c7565b63ffffffff8116811461195c57600080fd5b80356123e7816125b9565b801515811461195c57600080fd5b80356123e7816125d6565b6000610120828403121561260257600080fd5b61260a612479565b612613836125cb565b8152612621602084016123dc565b6020820152612632604084016123dc565b6040820152612643606084016123dc565b6060820152612654608084016123dc565b608082015260a083013560a082015260c083013560c082015261267960e084016125e4565b60e0820152610100928301359281019290925250919050565b6000602082840312156126a457600080fd5b813567ffffffffffffffff8111156126bb57600080fd5b6126c7848285016124c7565b949350505050565b600080604083850312156126e257600080fd5b823567ffffffffffffffff8111156126f957600080fd5b612705858286016124c7565b95602094909401359450505050565b6000806040838503121561272757600080fd5b50508035926020909101359150565b815163ffffffff1681526101808101602083015161275c602084018263ffffffff169052565b50604083015161277760408401826001600160a01b03169052565b50606083015161279260608401826001600160a01b03169052565b5060808301516127ad60808401826001600160a01b03169052565b5060a08301516127c860a08401826001600160a01b03169052565b5060c083015160c083015260e083015160e0830152610100808401518184015250610120808401516127fd8285018215159052565b5050610140838101519083015261016092830151929091019190915290565b60006020828403121561282e57600080fd5b813561144f816123c7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561085a5761085a612839565b808202811582820484141761085a5761085a612839565b6000826128c8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561085a5761085a612839565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361291157612911612839565b5060010190565b60005b8381101561293357818101518382015260200161291b565b50506000910152565b60e08152600088518060e084015261010061295d8282860160208e01612918565b63ffffffff9990991660208401526001600160a01b039788166040840152959096166060820152608081019390935260a0830191909152151560c0820152601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190910192915050565b80516123e7816125b9565b80516123e7816123c7565b80516123e7816125d6565b60006101808284031215612a0057600080fd5b612a086124a3565b612a11836129cc565b8152612a1f602084016129cc565b6020820152612a30604084016129d7565b6040820152612a41606084016129d7565b6060820152612a52608084016129d7565b6080820152612a6360a084016129d7565b60a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120612a968185016129e2565b908201526101408381015190820152610160928301519281019290925250919050565b600060208284031215612acb57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215612b1357600080fd5b815161144f816125d6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612b5f818460208701612918565b919091019291505056fea26469706673582212203bd946d03327296505c829a4894b0a06df193475064ebb0445d9c80a5699ab3164736f6c63430008140033","runtime-code":"0x60806040526004361061026a5760003560e01c80639010d07c11610153578063add98c70116100cb578063ca15c8731161007f578063d547741f11610064578063d547741f146107a1578063dcf844a7146107c1578063e00a83e0146107ee57600080fd5b8063ca15c8731461074d578063ccc574901461076d57600080fd5b8063b13aa2d6116100b0578063b13aa2d6146106f6578063b250fe6b14610716578063bf333f2c1461073657600080fd5b8063add98c70146106c0578063affed0e0146106e057600080fd5b8063a217fddf11610122578063a5bbe22b11610107578063a5bbe22b1461047f578063aa9641ab14610673578063ac11fb1a1461069357600080fd5b8063a217fddf1461062a578063a3ec191a1461063f57600080fd5b80639010d07c146104f857806391ad50391461053057806391d14854146105b2578063926d7d7f146105f657600080fd5b806341fcb612116101e65780635eb7d946116101b55780638379a24f1161019a5780638379a24f14610495578063886d36ff146104c55780638f0d6f17146104e557600080fd5b80635eb7d9461461045f578063820688d51461047f57600080fd5b806341fcb612146103e2578063458516941461040257806358f85880146104155780635960ccf21461042b57600080fd5b80630f5f6ed71161023d578063248a9ca311610222578063248a9ca3146103725780632f2ff15d146103a257806336568abe146103c257600080fd5b80630f5f6ed714610345578063190da5951461035b57600080fd5b806301ffc9a71461026f57806303ed0ee5146102a4578063051287bc146102e657806306f333f214610323575b600080fd5b34801561027b57600080fd5b5061028f61028a3660046122fc565b610804565b60405190151581526020015b60405180910390f35b3480156102b057600080fd5b506102d87f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b60405190815260200161029b565b3480156102f257600080fd5b5061031661030136600461233e565b60056020526000908152604090205460ff1681565b60405161029b9190612386565b34801561032f57600080fd5b5061034361033e3660046123ec565b610860565b005b34801561035157600080fd5b506102d861271081565b34801561036757600080fd5b506102d862093a8081565b34801561037e57600080fd5b506102d861038d36600461233e565b60009081526020819052604090206001015490565b3480156103ae57600080fd5b506103436103bd366004612425565b610927565b3480156103ce57600080fd5b506103436103dd366004612425565b610952565b3480156103ee57600080fd5b506103436103fd366004612572565b61099e565b6103436104103660046125ef565b610bd7565b34801561042157600080fd5b506102d860025481565b34801561043757600080fd5b506102d87fdb9556138406326f00296e13ea2ad7db24ba82381212d816b1a40c23b466b32781565b34801561046b57600080fd5b5061034361047a366004612692565b610ee5565b34801561048b57600080fd5b506102d861070881565b3480156104a157600080fd5b5061028f6104b036600461233e565b60076020526000908152604090205460ff1681565b3480156104d157600080fd5b506103436104e03660046126cf565b6110bd565b6103436104f3366004612692565b6111f0565b34801561050457600080fd5b50610518610513366004612714565b611437565b6040516001600160a01b03909116815260200161029b565b34801561053c57600080fd5b5061058661054b36600461233e565b6006602052600090815260409020546bffffffffffffffffffffffff8116906c0100000000000000000000000090046001600160a01b031682565b604080516bffffffffffffffffffffffff90931683526001600160a01b0390911660208301520161029b565b3480156105be57600080fd5b5061028f6105cd366004612425565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561060257600080fd5b506102d87fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b34801561063657600080fd5b506102d8600081565b34801561064b57600080fd5b506102d87f000000000000000000000000000000000000000000000000000000000000000081565b34801561067f57600080fd5b5061028f61068e366004612425565b611456565b34801561069f57600080fd5b506106b36106ae366004612692565b611559565b60405161029b9190612736565b3480156106cc57600080fd5b506103436106db36600461233e565b6115cc565b3480156106ec57600080fd5b506102d860085481565b34801561070257600080fd5b5061034361071136600461233e565b611735565b34801561072257600080fd5b5061034361073136600461233e565b611817565b34801561074257600080fd5b506102d8620f424081565b34801561075957600080fd5b506102d861076836600461233e565b61187f565b34801561077957600080fd5b506102d87f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b3480156107ad57600080fd5b506103436107bc366004612425565b611896565b3480156107cd57600080fd5b506102d86107dc36600461281c565b60036020526000908152604090205481565b3480156107fa57600080fd5b506102d860045481565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f00000000000000000000000000000000000000000000000000000000148061085a575061085a826118bb565b92915050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561088a81611952565b6001600160a01b038316600090815260036020526040812054908190036108b15750505050565b6001600160a01b0384166000818152600360205260408120556108d590848361195f565b604080516001600160a01b038087168252851660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b505050565b60008281526020819052604090206001015461094281611952565b61094c8383611a82565b50505050565b6001600160a01b0381163314610994576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109228282611ab7565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc46109c881611952565b8251602084012060006109da85611559565b9050600260008381526005602052604090205460ff166004811115610a0157610a01612357565b14610a38576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660209081526040918290208251808401909352546bffffffffffffffffffffffff811683526c0100000000000000000000000090046001600160a01b03169082018190523314610abb576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611610b08576040517f1992d0bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600560205260409020805460ff1916600317905561010082015115610b645761010082015160808301516001600160a01b031660009081526003602052604081208054909190610b5e908490612868565b90915550505b608082015160c0830151610b826001600160a01b038316888361195f565b604080516001600160a01b03848116825260208201849052891691339188917f582211c35a2139ac3bbaac74663c6a1f56c6cbb658b41fe11fd45a82074ac67891015b60405180910390a45050505050505050565b46816000015163ffffffff1603610c1a576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a08101511580610c2d575060c0810151155b15610c64576040517fe38820c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608101516001600160a01b03161580610c89575060808101516001600160a01b0316155b15610cc0576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ccc61070842612868565b8161010001511015610d0a576040517f04b7fcc800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d1f3083606001518460a00151611ae4565b90506000806002541115610d4c57620f424060025483610d3f919061287b565b610d499190612892565b90505b610d5681836128cd565b915060006040518061018001604052804663ffffffff168152602001856000015163ffffffff16815260200185602001516001600160a01b0316815260200185604001516001600160a01b0316815260200185606001516001600160a01b0316815260200185608001516001600160a01b031681526020018481526020018560c0015181526020018381526020018560e0015115158152602001856101000151815260200160086000815480929190610e0e906128e0565b909155509052604051610e249190602001612736565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152828252805160208083019190912060008181526005835293909320805460ff191660011790558701518751606089015160808a015160c08b015160e08c015195985095966001600160a01b039094169587957f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a95610ed6958b959094909390928e9261293c565b60405180910390a35050505050565b805160208201206000610ef783611559565b3360009081527fd2043bf65931af3dbecf60d0db8f40e4160406d7beb00522f4200cf4944a1eb8602052604090205490915060ff1615610f74578061014001514211610f6f576040517fe15ff9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fc0565b62093a80816101400151610f889190612868565b4211610fc0576040517fe15ff9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008381526005602052604090205460ff166004811115610fe557610fe5612357565b1461101c576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260056020526040808220805460ff19166004179055820151608083015161010084015160c0850151929391926110579190612868565b905061106d6001600160a01b038316848361195f565b604080516001600160a01b0384811682526020820184905285169187917fb4c55c0c9bc613519b920e88748090150b890a875d307f21bea7d4fb2e8bc958910160405180910390a3505050505050565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc46110e781611952565b82516020840120600160008281526005602052604090205460ff16600481111561111357611113612357565b1461114a576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526005602090815260408083208054600260ff19909116179055805180820182526bffffffffffffffffffffffff4281168252338285018181528787526006865295849020925195516001600160a01b03166c0100000000000000000000000002959091169490941790555185815283917f4ac8af8a2cd87193d64dfc7a3b8d9923b714ec528b18725d080aa1299be0c5e4910160405180910390a350505050565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc461121a81611952565b81516020830120600061122c84611559565b90504663ffffffff16816020015163ffffffff1614611277576040517f7029fdf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8061014001514211156112b6576040517f559895a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526007602052604090205460ff16156112ff576040517fbef7bb7d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600760205260409020805460ff19166001179055606081015160a082015160e083015160045461012085015161134857506000611342848484611ae4565b506113b9565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b0384160161138c5761134284846113878486612868565b611ae4565b611397848484611ae4565b506113b78473eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee83611ae4565b505b845160808087015160a08089015160c0808b015160e08c01516040805163ffffffff90991689526001600160a01b0396871660208a0152938616938801939093526060870152938501528301849052861691339189917ff8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c9101610bc5565b600082815260016020526040812061144f9083611cb3565b9392505050565b6000600260008481526005602052604090205460ff16600481111561147d5761147d612357565b146114b4576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600660209081526040918290208251808401909352546bffffffffffffffffffffffff811683526001600160a01b036c01000000000000000000000000909104811691830182905284161461153a576040517f4af43a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516107089042036bffffffffffffffffffffffff1611949350505050565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201528251909161085a91840181019084016129ed565b7f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d6115f681611952565b600260008381526005602052604090205460ff16600481111561161b5761161b612357565b14611652576040517f4145817200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600660209081526040918290208251808401909352546bffffffffffffffffffffffff8082168085526c010000000000000000000000009092046001600160a01b031693909201929092526107089142031611156116e1576040517f3e908aac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040808320805460ff19166001179055600690915280822082905551339184917f0695cf1d39b3055dcd0fe02d8b47eaf0d5a13e1996de925de59d0ef9b7f7fad49190a35050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561175f81611952565b6127108211156117d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d61780000000000000000000000000000000060448201526064015b60405180910390fd5b600280549083905560408051828152602081018590527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a1505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5561184181611952565b600480549083905560408051828152602081018590527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa910161180a565b600081815260016020526040812061085a90611cbf565b6000828152602081905260409020600101546118b181611952565b61094c8383611ab7565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061085a57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461085a565b61195c8133611cc9565b50565b306001600160a01b0383160361197457505050565b8060000361198157505050565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03841601611a6e576000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146119fe576040519150601f19603f3d011682016040523d82523d6000602084013e611a03565b606091505b505090508061094c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c65640000000000000000000000000060448201526064016117c7565b6109226001600160a01b0384168383611d39565b600080611a8f8484611dad565b9050801561144f576000848152600160205260409020611aaf9084611e57565b509392505050565b600080611ac48484611e6c565b9050801561144f576000848152600160205260409020611aaf9084611eef565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611c4d57611b1c836001600160a01b0316611f04565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528416906370a0823190602401602060405180830381865afa158015611b7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9f9190612ab9565b9050611bb66001600160a01b038416338685611faa565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528291908516906370a0823190602401602060405180830381865afa158015611c18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c3c9190612ab9565b611c4691906128cd565b905061144f565b348214611c86576040517f81de0bf300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0384163014611caa57611caa6001600160a01b038416858461195f565b50349392505050565b600061144f8383611fe3565b600061085a825490565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16611d35576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602481018390526044016117c7565b5050565b6040516001600160a01b0383811660248301526044820183905261092291859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061200d565b6000828152602081815260408083206001600160a01b038516845290915281205460ff16611e4f576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055611e073390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161085a565b50600061085a565b600061144f836001600160a01b038416612089565b6000828152602081815260408083206001600160a01b038516845290915281205460ff1615611e4f576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161085a565b600061144f836001600160a01b0384166120d0565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03821601611f66576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03163b60000361195c576040517f7f523fe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b03848116602483015283811660448301526064820183905261094c9186918216906323b872dd90608401611d66565b6000826000018281548110611ffa57611ffa612ad2565b9060005260206000200154905092915050565b60006120226001600160a01b038416836121c3565b905080516000141580156120475750808060200190518101906120459190612b01565b155b15610922576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024016117c7565b6000818152600183016020526040812054611e4f5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561085a565b600081815260018301602052604081205480156121b95760006120f46001836128cd565b8554909150600090612108906001906128cd565b905080821461216d57600086600001828154811061212857612128612ad2565b906000526020600020015490508087600001848154811061214b5761214b612ad2565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061217e5761217e612b1e565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061085a565b600091505061085a565b606061144f8383600084600080856001600160a01b031684866040516121e99190612b4d565b60006040518083038185875af1925050503d8060008114612226576040519150601f19603f3d011682016040523d82523d6000602084013e61222b565b606091505b509150915061223b868383612245565b9695505050505050565b60608261225a57612255826122ba565b61144f565b815115801561227157506001600160a01b0384163b155b156122b3576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016117c7565b508061144f565b8051156122ca5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561230e57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461144f57600080fd5b60006020828403121561235057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600583106123c1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6001600160a01b038116811461195c57600080fd5b80356123e7816123c7565b919050565b600080604083850312156123ff57600080fd5b823561240a816123c7565b9150602083013561241a816123c7565b809150509250929050565b6000806040838503121561243857600080fd5b82359150602083013561241a816123c7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171561249d5761249d61244a565b60405290565b604051610180810167ffffffffffffffff8111828210171561249d5761249d61244a565b600082601f8301126124d857600080fd5b813567ffffffffffffffff808211156124f3576124f361244a565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156125395761253961244a565b8160405283815286602085880101111561255257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806040838503121561258557600080fd5b823567ffffffffffffffff81111561259c57600080fd5b6125a8858286016124c7565b925050602083013561241a816123c7565b63ffffffff8116811461195c57600080fd5b80356123e7816125b9565b801515811461195c57600080fd5b80356123e7816125d6565b6000610120828403121561260257600080fd5b61260a612479565b612613836125cb565b8152612621602084016123dc565b6020820152612632604084016123dc565b6040820152612643606084016123dc565b6060820152612654608084016123dc565b608082015260a083013560a082015260c083013560c082015261267960e084016125e4565b60e0820152610100928301359281019290925250919050565b6000602082840312156126a457600080fd5b813567ffffffffffffffff8111156126bb57600080fd5b6126c7848285016124c7565b949350505050565b600080604083850312156126e257600080fd5b823567ffffffffffffffff8111156126f957600080fd5b612705858286016124c7565b95602094909401359450505050565b6000806040838503121561272757600080fd5b50508035926020909101359150565b815163ffffffff1681526101808101602083015161275c602084018263ffffffff169052565b50604083015161277760408401826001600160a01b03169052565b50606083015161279260608401826001600160a01b03169052565b5060808301516127ad60808401826001600160a01b03169052565b5060a08301516127c860a08401826001600160a01b03169052565b5060c083015160c083015260e083015160e0830152610100808401518184015250610120808401516127fd8285018215159052565b5050610140838101519083015261016092830151929091019190915290565b60006020828403121561282e57600080fd5b813561144f816123c7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561085a5761085a612839565b808202811582820484141761085a5761085a612839565b6000826128c8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561085a5761085a612839565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361291157612911612839565b5060010190565b60005b8381101561293357818101518382015260200161291b565b50506000910152565b60e08152600088518060e084015261010061295d8282860160208e01612918565b63ffffffff9990991660208401526001600160a01b039788166040840152959096166060820152608081019390935260a0830191909152151560c0820152601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190910192915050565b80516123e7816125b9565b80516123e7816123c7565b80516123e7816125d6565b60006101808284031215612a0057600080fd5b612a086124a3565b612a11836129cc565b8152612a1f602084016129cc565b6020820152612a30604084016129d7565b6040820152612a41606084016129d7565b6060820152612a52608084016129d7565b6080820152612a6360a084016129d7565b60a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120612a968185016129e2565b908201526101408381015190820152610160928301519281019290925250919050565b600060208284031215612acb57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215612b1357600080fd5b815161144f816125d6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612b5f818460208701612918565b919091019291505056fea26469706673582212203bd946d03327296505c829a4894b0a06df193475064ebb0445d9c80a5699ab3164736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n )\n external\n {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"58205:11304:0:-:0;;;59380:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;59414:6;57196:38;46368:4;59414:6;57196:10;:38::i;:::-;-1:-1:-1;;59446:12:0::1;59432:26;::::0;-1:-1:-1;58205:11304:0;;55681:257;55767:4;;55798:31;55815:4;55821:7;55798:16;:31::i;:::-;55783:46;;55843:7;55839:69;;;55866:18;;;;:12;:18;;;;;:31;;55889:7;55866:22;:31::i;:::-;;55839:69;55924:7;-1:-1:-1;55681:257:0;;;;;:::o;50315:316::-;50392:4;47090:12;;;;;;;;;;;-1:-1:-1;;;;;47090:29:0;;;;;;;;;;;;50408:217;;50451:6;:12;;;;;;;;;;;-1:-1:-1;;;;;50451:29:0;;;;;;;;;:36;;-1:-1:-1;;50451:36:0;50483:4;50451:36;;;50533:12;22406:10;;22327:96;50533:12;-1:-1:-1;;;;;50506:40:0;50524:7;-1:-1:-1;;;;;50506:40:0;50518:4;50506:40;;;;;;;;;;-1:-1:-1;50567:4:0;50560:11;;50408:217;-1:-1:-1;50609:5:0;50602:12;;31852:150;31922:4;31945:50;31950:3;-1:-1:-1;;;;;31970:23:0;;25840:4;27896:21;;;:14;;;:21;;;;;;25856:321;;-1:-1:-1;25898:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;26080:18;;26056:21;;;:14;;;:21;;;;;;:42;;;;26112:11;;14:290:1;84:6;137:2;125:9;116:7;112:23;108:32;105:52;;;153:1;150;143:12;105:52;179:16;;-1:-1:-1;;;;;224:31:1;;214:42;;204:70;;270:1;267;260:12;14:290;58205:11304:0;;;;;;;;;;;;","srcMapRuntime":"58205:11304:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54341:212;;;;;;;;;;-1:-1:-1;54341:212:0;;;;;:::i;:::-;;:::i;:::-;;;612:14:1;;605:22;587:41;;575:2;560:18;54341:212:0;;;;;;;;56571:60;;;;;;;;;;;;56608:23;56571:60;;;;;785:25:1;;;773:2;758:18;56571:60:0;639:177:1;58932:54:0;;;;;;;;;;-1:-1:-1;58932:54:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;57543:359::-;;;;;;;;;;-1:-1:-1;57543:359:0;;;;;:::i;:::-;;:::i;:::-;;56753:45;;;;;;;;;;;;56792:6;56753:45;;58530;;;;;;;;;;;;58569:6;58530:45;;47946:120;;;;;;;;;;-1:-1:-1;47946:120:0;;;;;:::i;:::-;48011:7;48037:12;;;;;;;;;;:22;;;;47946:120;48362:136;;;;;;;;;;-1:-1:-1;48362:136:0;;;;;:::i;:::-;;:::i;49464:245::-;;;;;;;;;;-1:-1:-1;49464:245:0;;;;;:::i;:::-;;:::i;66607:1146::-;;;;;;;;;;-1:-1:-1;66607:1146:0;;;;;:::i;:::-;;:::i;61065:2114::-;;;;;;:::i;:::-;;:::i;56915:30::-;;;;;;;;;;;;;;;;56499:66;;;;;;;;;;;;56539:26;56499:66;;68354:1153;;;;;;;;;;-1:-1:-1;68354:1153:0;;;;;:::i;:::-;;:::i;58662:56::-;;;;;;;;;;;;58708:10;58662:56;;59177:44;;;;;;;;;;-1:-1:-1;59177:44:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;64973:567;;;;;;;;;;-1:-1:-1;64973:567:0;;;;;:::i;:::-;;:::i;63217:1718::-;;;;;;:::i;:::-;;:::i;55138:142::-;;;;;;;;;;-1:-1:-1;55138:142:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;7391:55:1;;;7373:74;;7361:2;7346:18;55138:142:0;7227:226:1;59051:51:0;;;;;;;;;;-1:-1:-1;59051:51:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;59051:51:0;;;;;;;7660:26:1;7648:39;;;7630:58;;-1:-1:-1;;;;;7724:55:1;;;7719:2;7704:18;;7697:83;7603:18;59051:51:0;7458:328:1;46990:136:0;;;;;;;;;;-1:-1:-1;46990:136:0;;;;;:::i;:::-;47067:4;47090:12;;;;;;;;;;;-1:-1:-1;;;;;47090:29:0;;;;;;;;;;;;;;;46990:136;56429:64;;;;;;;;;;;;56468:25;56429:64;;46323:49;;;;;;;;;;-1:-1:-1;46323:49:0;46368:4;46323:49;;59337:36;;;;;;;;;;;;;;;66196:373;;;;;;;;;;-1:-1:-1;66196:373:0;;;;;:::i;:::-;;:::i;60864:163::-;;;;;;;;;;-1:-1:-1;60864:163:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;67791:525::-;;;;;;;;;;-1:-1:-1;67791:525:0;;;;;:::i;:::-;;:::i;59260:20::-;;;;;;;;;;;;;;;;57247:290;;;;;;;;;;-1:-1:-1;57247:290:0;;;;;:::i;:::-;;:::i;57908:264::-;;;;;;;;;;-1:-1:-1;57908:264:0;;;;;:::i;:::-;;:::i;56710:37::-;;;;;;;;;;;;56744:3;56710:37;;55448:131;;;;;;;;;;-1:-1:-1;55448:131:0;;;;;:::i;:::-;;:::i;56637:66::-;;;;;;;;;;;;56677:26;56637:66;;48778:138;;;;;;;;;;-1:-1:-1;48778:138:0;;;;;:::i;:::-;;:::i;57001:47::-;;;;;;;;;;-1:-1:-1;57001:47:0;;;;;:::i;:::-;;;;;;;;;;;;;;57122:29;;;;;;;;;;;;;;;;54341:212;54426:4;54449:57;;;54464:42;54449:57;;:97;;;54510:36;54534:11;54510:23;:36::i;:::-;54442:104;54341:212;-1:-1:-1;;54341:212:0:o;57543:359::-;56677:26;46600:16;46611:4;46600:10;:16::i;:::-;-1:-1:-1;;;;;57667:19:0;::::1;57647:17;57667:19:::0;;;:12:::1;:19;::::0;;;;;;57700:14;;;57696:27:::1;;57716:7;57543:359:::0;;;:::o;57696:27::-:1;-1:-1:-1::0;;;;;57764:19:0;::::1;57786:1;57764:19:::0;;;:12:::1;:19;::::0;;;;:23;57797:45:::1;::::0;57821:9;57832;57797:23:::1;:45::i;:::-;57857:38;::::0;;-1:-1:-1;;;;;9986:15:1;;;9968:34;;10038:15;;10033:2;10018:18;;10011:43;10070:18;;;10063:34;;;57857:38:0::1;::::0;9895:2:1;9880:18;57857:38:0::1;;;;;;;57637:265;46626:1;57543:359:::0;;;:::o;48362:136::-;48011:7;48037:12;;;;;;;;;;:22;;;46600:16;46611:4;46600:10;:16::i;:::-;48466:25:::1;48477:4;48483:7;48466:10;:25::i;:::-;;48362:136:::0;;;:::o;49464:245::-;-1:-1:-1;;;;;49557:34:0;;22406:10;49557:34;49553:102;;49614:30;;;;;;;;;;;;;;49553:102;49665:37;49677:4;49683:18;49665:11;:37::i;66607:1146::-;56468:25;46600:16;46611:4;46600:10;:16::i;:::-;66722:18;;::::1;::::0;::::1;::::0;66698:21:::1;66789:29;66732:7:::0;66789:20:::1;:29::i;:::-;66750:68:::0;-1:-1:-1;66936:27:0::1;66903:29;::::0;;;:14:::1;:29;::::0;;;;;::::1;;:60;::::0;::::1;;;;;;:::i;:::-;;66899:90;;66972:17;;;;;;;;;;;;;;66899:90;67000:24;67027:27:::0;;;:12:::1;:27;::::0;;;;;;;;67000:54;;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;;;;::::1;-1:-1:-1::0;;;;;67000:54:0::1;::::0;;::::1;::::0;;;67085:10:::1;67068:27;67064:57;;67104:17;;;;;;;;;;;;;;67064:57;66126:15:::0;;58424:10:::1;::::0;66107:15;66100:41;66092:49;;67135:35:::1;67131:72;;67179:24;;;;;;;;;;;;;;67131:72;67214:29;::::0;;;:14:::1;:29;::::0;;;;:60;;-1:-1:-1;;67214:60:0::1;67246:28;67214:60;::::0;;67349:27:::1;::::0;::::1;::::0;:31;67345:105:::1;;67423:27;::::0;::::1;::::0;67395:23:::1;::::0;::::1;::::0;-1:-1:-1;;;;;67382:37:0::1;;::::0;;;:12:::1;:37;::::0;;;;:68;;:37;;;:68:::1;::::0;67423:27;;67382:68:::1;:::i;:::-;::::0;;;-1:-1:-1;;67345:105:0::1;67545:23;::::0;::::1;::::0;67595:24:::1;::::0;::::1;::::0;67629:35:::1;-1:-1:-1::0;;;;;67629:23:0;::::1;67653:2:::0;67595:24;67629:23:::1;:35::i;:::-;67680:66;::::0;;-1:-1:-1;;;;;10619:55:1;;;10601:74;;10706:2;10691:18;;10684:34;;;67680:66:0;::::1;::::0;67716:10:::1;::::0;67701:13;;67680:66:::1;::::0;10574:18:1;67680:66:0::1;;;;;;;;66688:1065;;;;;66607:1146:::0;;;:::o;61065:2114::-;61192:13;61171:6;:17;;;:34;;;61167:63;;61214:16;;;;;;;;;;;;;;61167:63;61244:19;;;;:24;;:50;;-1:-1:-1;61272:17:0;;;;:22;61244:50;61240:80;;;61303:17;;;;;;;;;;;;;;61240:80;61334:18;;;;-1:-1:-1;;;;;61334:32:0;;;:66;;-1:-1:-1;61370:16:0;;;;-1:-1:-1;;;;;61370:30:0;;61334:66;61330:92;;;61409:13;;;;;;;;;;;;;;61330:92;61454:37;58708:10;61454:15;:37;:::i;:::-;61436:6;:15;;;:55;61432:86;;;61500:18;;;;;;;;;;;;;;61432:86;61653:20;61676:66;61695:4;61702:6;:18;;;61722:6;:19;;;61676:10;:66::i;:::-;61653:89;;61810:23;61865:1;61847:15;;:19;61843:85;;;56744:3;61902:15;;61887:12;:30;;;;:::i;:::-;61886:42;;;;:::i;:::-;61868:60;;61843:85;61938:31;61954:15;61938:31;;:::i;:::-;;;62082:20;62129:618;;;;;;;;62187:13;62129:618;;;;;;62232:6;:17;;;62129:618;;;;;;62281:6;:13;;;-1:-1:-1;;;;;62129:618:0;;;;;62327:6;:9;;;-1:-1:-1;;;;;62129:618:0;;;;;62367:6;:18;;;-1:-1:-1;;;;;62129:618:0;;;;;62414:6;:16;;;-1:-1:-1;;;;;62129:618:0;;;;;62462:12;62129:618;;;;62504:6;:17;;;62129:618;;;;62556:15;62129:618;;;;62603:6;:19;;;62129:618;;;;;;62650:6;:15;;;62129:618;;;;62690:5;;:7;;;;;;;;;:::i;:::-;;;;-1:-1:-1;62129:618:0;;62105:652;;;;;;;;:::i;:::-;;;;;;;;;;;;;;62791:18;;62105:652;62791:18;;;;;;;62767:21;62819:29;;;:14;:29;;;;;;:54;;-1:-1:-1;;62819:54:0;62851:22;62819:54;;;62945:13;;;62993:17;;63024:18;;;;63056:16;;;;63112:17;;;;63143:19;;;;62105:652;;-1:-1:-1;62791:18:0;;-1:-1:-1;;;;;62889:283:0;;;;62791:18;;62889:283;;;;62105:652;;62993:17;;63024:18;;63056:16;;63086:12;;62889:283;:::i;:::-;;;;;;;;61126:2053;;;;61065:2114;:::o;68354:1153::-;68435:18;;;;;;68411:21;68502:29;68445:7;68502:20;:29::i;:::-;68569:10;47067:4;47090:29;;;:12;;:29;:12;:29;;;68463:68;;-1:-1:-1;47090:29:0;;68542:382;;;68677:11;:20;;;68658:15;:39;68654:73;;68706:21;;;;;;;;;;;;;;68654:73;68542:382;;;58569:6;68848:11;:20;;;:35;;;;:::i;:::-;68829:15;:54;68825:88;;68892:21;;;;;;;;;;;;;;68825:88;69033:22;69000:29;;;;:14;:29;;;;;;;;:55;;;;;;;;:::i;:::-;;68996:85;;69064:17;;;;;;;;;;;;;;68996:85;69091:29;;;;:14;:29;;;;;;:53;;-1:-1:-1;;69091:53:0;69123:21;69091:53;;;69230:24;;;69280:23;;;;69357:27;;;;69330:24;;;;69230;;69280:23;;69330:54;;69357:27;69330:54;:::i;:::-;69313:71;-1:-1:-1;69394:35:0;-1:-1:-1;;;;;69394:23:0;;69418:2;69313:71;69394:23;:35::i;:::-;69445:55;;;-1:-1:-1;;;;;10619:55:1;;;10601:74;;10706:2;10691:18;;10684:34;;;69445:55:0;;;69467:13;;69445:55;;10574:18:1;69445:55:0;;;;;;;68401:1106;;;;;68354:1153;:::o;64973:567::-;56468:25;46600:16;46611:4;46600:10;:16::i;:::-;65096:18;;::::1;::::0;::::1;::::0;65217:22:::1;65184:29;::::0;;;:14:::1;:29;::::0;;;;;::::1;;:55;::::0;::::1;;;;;;:::i;:::-;;65180:85;;65248:17;;;;;;;;;;;;;;65180:85;65275:29;::::0;;;:14:::1;:29;::::0;;;;;;;:59;;65307:27:::1;-1:-1:-1::0;;65275:59:0;;::::1;;::::0;;65374:70;;;;::::1;::::0;;::::1;65405:15;65374:70:::0;::::1;::::0;;65432:10:::1;65374:70:::0;;::::1;::::0;;;65344:27;;;:12:::1;:27:::0;;;;;;:100;;;;-1:-1:-1;;;;;65344:100:0::1;::::0;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;65475:58;785:25:1;;;65275:29:0;;65475:58:::1;::::0;758:18:1;65475:58:0::1;;;;;;;65062:478;64973:567:::0;;;:::o;63217:1718::-;56468:25;46600:16;46611:4;46600:10;:16::i;:::-;63328:18;;::::1;::::0;::::1;::::0;63304:21:::1;63395:29;63338:7:::0;63395:20:::1;:29::i;:::-;63356:68;;63472:13;63438:48;;:11;:23;;;:48;;;63434:77;;63495:16;;;;;;;;;;;;;;63434:77;63607:11;:20;;;63589:15;:38;63585:69;;;63636:18;;;;;;;;;;;;;;63585:69;63715:27;::::0;;;:12:::1;:27;::::0;;;;;::::1;;63711:60;;;63751:20;;;;;;;;;;;;;;63711:60;63781:27;::::0;;;:12:::1;:27;::::0;;;;:34;;-1:-1:-1;;63781:34:0::1;63811:4;63781:34;::::0;;63928:25:::1;::::0;::::1;::::0;63979:21:::1;::::0;::::1;::::0;64027:22:::1;::::0;::::1;::::0;64077:14:::1;::::0;64106:24:::1;::::0;::::1;::::0;64101:517:::1;;-1:-1:-1::0;64184:1:0::1;64199:29;64210:2:::0;64214:5;64221:6;64199:10:::1;:29::i;:::-;;64101:517;;;64249:38:::0;-1:-1:-1;;;;;64249:38:0;::::1;::::0;64245:373:::1;;64369:38;64380:2:::0;64384:5;64391:15:::1;64400:6:::0;64391;:15:::1;:::i;:::-;64369:10;:38::i;64245:373::-;64511:29;64522:2;64526:5;64533:6;64511:10;:29::i;:::-;;64554:53;64565:2;51330:42;64600:6;64554:10;:53::i;:::-;;64245:373;64727:25:::0;;64766:23:::1;::::0;;::::1;::::0;64803:21:::1;::::0;;::::1;::::0;64838:24:::1;::::0;;::::1;::::0;64876:22:::1;::::0;::::1;::::0;64633:295:::1;::::0;;13103:10:1;13091:23;;;13073:42;;-1:-1:-1;;;;;13212:15:1;;;13207:2;13192:18;;13185:43;13264:15;;;13244:18;;;13237:43;;;;13311:2;13296:18;;13289:34;13339:19;;;13332:35;13383:19;;13376:35;;;64633:295:0;::::1;::::0;64687:10:::1;::::0;64660:13;;64633:295:::1;::::0;13045:19:1;64633:295:0::1;12788:629:1::0;55138:142:0;55219:7;55245:18;;;:12;:18;;;;;:28;;55267:5;55245:21;:28::i;:::-;55238:35;55138:142;-1:-1:-1;;;55138:142:0:o;66196:373::-;66277:4;66330:27;66297:29;;;;:14;:29;;;;;;;;:60;;;;;;;;:::i;:::-;;66293:90;;66366:17;;;;;;;;;;;;;;66293:90;66393:24;66420:27;;;:12;:27;;;;;;;;;66393:54;;;;;;;;;;;;;;-1:-1:-1;;;;;66393:54:0;;;;;;;;;;;;66461:24;;;66457:54;;66494:17;;;;;;;;;;;;;;66457:54;66126:15;;58424:10;;66107:15;66100:41;66092:49;;66528:34;;66196:373;-1:-1:-1;;;;66196:373:0:o;60864:163::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60980:40:0;;-1:-1:-1;;60980:40:0;;;;;;;;;;:::i;67791:525::-;56608:23;46600:16;46611:4;46600:10;:16::i;:::-;67908:27:::1;67875:29;::::0;;;:14:::1;:29;::::0;;;;;::::1;;:60;::::0;::::1;;;;;;:::i;:::-;;67871:90;;67944:17;;;;;;;;;;;;;;67871:90;67986:27;::::0;;;:12:::1;:27;::::0;;;;;;;;67975:39;;;;::::1;::::0;;;;::::1;::::0;;::::1;::::0;;;;;;::::1;-1:-1:-1::0;;;;;67975:39:0::1;::::0;;;::::1;::::0;;;;58424:10:::1;::::0;66107:15;66100:41;66092:49;67975:56:::1;67971:90;;;68040:21;;;;;;;;;;;;;;67971:90;68149:29;::::0;;;:14:::1;:29;::::0;;;;;;;:54;;-1:-1:-1;;68149:54:0::1;68181:22;68149:54;::::0;;68220:12:::1;:27:::0;;;;;;68213:34;;;68263:46;68298:10:::1;::::0;68149:29;;68263:46:::1;::::0;68149:29;68263:46:::1;67791:525:::0;;:::o;57247:290::-;56677:26;46600:16;46611:4;46600:10;:16::i;:::-;56792:6:::1;57346:10;:26;;57338:55;;;::::0;::::1;::::0;;15233:2:1;57338:55:0::1;::::0;::::1;15215:21:1::0;15272:2;15252:18;;;15245:30;15311:18;15291;;;15284:46;15347:18;;57338:55:0::1;;;;;;;;;57424:15;::::0;;57449:28;;;;57492:38:::1;::::0;;15550:25:1;;;15606:2;15591:18;;15584:34;;;57492:38:0::1;::::0;15523:18:1;57492:38:0::1;;;;;;;;57328:209;57247:290:::0;;:::o;57908:264::-;56677:26;46600:16;46611:4;46600:10;:16::i;:::-;58033:14:::1;::::0;;58057:34;;;;58106:59:::1;::::0;;15550:25:1;;;15606:2;15591:18;;15584:34;;;58106:59:0::1;::::0;15523:18:1;58106:59:0::1;15376:248:1::0;55448:131:0;55519:7;55545:18;;;:12;:18;;;;;:27;;:25;:27::i;48778:138::-;48011:7;48037:12;;;;;;;;;;:22;;;46600:16;46611:4;46600:10;:16::i;:::-;48883:26:::1;48895:4;48901:7;48883:11;:26::i;46701:202::-:0;46786:4;46809:47;;;46824:32;46809:47;;:87;;-1:-1:-1;38614:25:0;38599:40;;;;46860:36;38500:146;47335:103;47401:30;47412:4;22406:10;47401;:30::i;:::-;47335:103;:::o;51613:653::-;51788:4;-1:-1:-1;;;;;51774:19:0;;;51770:32;;51613:653;;;:::o;51770:32::-;51874:5;51883:1;51874:10;51870:23;;51613:653;;;:::o;51870:23::-;51906:20;-1:-1:-1;;;;;51906:20:0;;;51902:358;;52086:12;52103:2;-1:-1:-1;;;;;52103:7:0;52118:5;52103:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52085:43;;;52150:7;52142:39;;;;;;;16041:2:1;52142:39:0;;;16023:21:1;16080:2;16060:18;;;16053:30;16119:21;16099:18;;;16092:49;16158:18;;52142:39:0;15839:343:1;51902:358:0;52212:37;-1:-1:-1;;;;;52212:26:0;;52239:2;52243:5;52212:26;:37::i;55681:257::-;55767:4;55783:12;55798:31;55815:4;55821:7;55798:16;:31::i;:::-;55783:46;;55843:7;55839:69;;;55866:18;;;;:12;:18;;;;;:31;;55889:7;55866:22;:31::i;:::-;;55924:7;55681:257;-1:-1:-1;;;55681:257:0:o;56041:262::-;56128:4;56144:12;56159:32;56177:4;56183:7;56159:17;:32::i;:::-;56144:47;;56205:7;56201:72;;;56228:18;;;;:12;:18;;;;;:34;;56254:7;56228:25;:34::i;59649:1177::-;59737:20;-1:-1:-1;;;;;59773:38:0;;51330:42;59773:38;59769:1051;;59827:24;:5;-1:-1:-1;;;;;59827:22:0;;:24::i;:::-;59932:34;;;;;-1:-1:-1;;;;;7391:55:1;;;59932:34:0;;;7373:74:1;59932:23:0;;;;;7346:18:1;;59932:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;59917:49;-1:-1:-1;60112:61:0;-1:-1:-1;;;;;60112:30:0;;60143:10;60155:9;60166:6;60112:30;:61::i;:::-;60309:34;;;;;-1:-1:-1;;;;;7391:55:1;;;60309:34:0;;;7373:74:1;60346:12:0;;60309:23;;;;;;7346:18:1;;60309:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:49;;;;:::i;:::-;60294:64;;59769:1051;;;60480:9;60470:6;:19;60466:51;;60498:19;;;;;;;;;;;;;;60466:51;-1:-1:-1;;;;;60598:26:0;;60619:4;60598:26;60594:74;;60626:42;-1:-1:-1;;;;;60626:23:0;;60650:9;60661:6;60626:23;:42::i;:::-;-1:-1:-1;60800:9:0;59649:1177;;;;;:::o;33110:156::-;33184:7;33234:22;33238:3;33250:5;33234:3;:22::i;32653:115::-;32716:7;32742:19;32750:3;28092:18;;28010:107;47568:197;47067:4;47090:12;;;;;;;;;;;-1:-1:-1;;;;;47090:29:0;;;;;;;;;;;;47651:108;;47701:47;;;;;-1:-1:-1;;;;;10619:55:1;;47701:47:0;;;10601:74:1;10691:18;;;10684:34;;;10574:18;;47701:47:0;10427:297:1;47651:108:0;47568:197;;:::o;39818:160::-;39927:43;;-1:-1:-1;;;;;10619:55:1;;;39927:43:0;;;10601:74:1;10691:18;;;10684:34;;;39900:71:0;;39920:5;;39942:14;;;;;10574:18:1;;39927:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39900:19;:71::i;50315:316::-;50392:4;47090:12;;;;;;;;;;;-1:-1:-1;;;;;47090:29:0;;;;;;;;;;;;50408:217;;50451:6;:12;;;;;;;;;;;-1:-1:-1;;;;;50451:29:0;;;;;;;;;:36;;-1:-1:-1;;50451:36:0;50483:4;50451:36;;;50533:12;22406:10;;22327:96;50533:12;-1:-1:-1;;;;;50506:40:0;50524:7;-1:-1:-1;;;;;50506:40:0;50518:4;50506:40;;;;;;;;;;-1:-1:-1;50567:4:0;50560:11;;50408:217;-1:-1:-1;50609:5:0;50602:12;;31852:150;31922:4;31945:50;31950:3;-1:-1:-1;;;;;31970:23:0;;31945:4;:50::i;50866:317::-;50944:4;47090:12;;;;;;;;;;;-1:-1:-1;;;;;47090:29:0;;;;;;;;;;;;50960:217;;;51034:5;51002:12;;;;;;;;;;;-1:-1:-1;;;;;51002:29:0;;;;;;;;;;:37;;-1:-1:-1;;51002:37:0;;;51058:40;22406:10;;51002:12;;51058:40;;51034:5;51058:40;-1:-1:-1;51119:4:0;51112:11;;32170:156;32243:4;32266:53;32274:3;-1:-1:-1;;;;;32294:23:0;;32266:7;:53::i;53430:344::-;53597:38;-1:-1:-1;;;;;53597:38:0;;;53593:69;;53644:18;;;;;;;;;;;;;;53593:69;53718:5;-1:-1:-1;;;;;53718:17:0;;53739:1;53718:22;53714:53;;53749:18;;;;;;;;;;;;;;40217:188;40344:53;;-1:-1:-1;;;;;9986:15:1;;;40344:53:0;;;9968:34:1;10038:15;;;10018:18;;;10011:43;10070:18;;;10063:34;;;40317:81:0;;40337:5;;40359:18;;;;;9880::1;;40344:53:0;9705:398:1;28459:118:0;28526:7;28552:3;:11;;28564:5;28552:18;;;;;;;;:::i;:::-;;;;;;;;;28545:25;;28459:118;;;;:::o;42574:629::-;42993:23;43019:33;-1:-1:-1;;;;;43019:27:0;;43047:4;43019:27;:33::i;:::-;42993:59;;43066:10;:17;43087:1;43066:22;;:57;;;;;43104:10;43093:30;;;;;;;;;;;;:::i;:::-;43092:31;43066:57;43062:135;;;43146:40;;;;;-1:-1:-1;;;;;7391:55:1;;43146:40:0;;;7373:74:1;7346:18;;43146:40:0;7227:226:1;25777:406:0;25840:4;27896:21;;;:14;;;:21;;;;;;25856:321;;-1:-1:-1;25898:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;26080:18;;26056:21;;;:14;;;:21;;;;;;:42;;;;26112:11;;26351:1368;26417:4;26546:21;;;:14;;;:21;;;;;;26582:13;;26578:1135;;26949:18;26970:12;26981:1;26970:8;:12;:::i;:::-;27016:18;;26949:33;;-1:-1:-1;26996:17:0;;27016:22;;27037:1;;27016:22;:::i;:::-;26996:42;;27071:9;27057:10;:23;27053:378;;27100:17;27120:3;:11;;27132:9;27120:22;;;;;;;;:::i;:::-;;;;;;;;;27100:42;;27267:9;27241:3;:11;;27253:10;27241:23;;;;;;;;:::i;:::-;;;;;;;;;;;;:35;;;;27380:25;;;:14;;;:25;;;;;:36;;;27053:378;27509:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;27612:3;:14;;:21;27627:5;27612:21;;;;;;;;;;;27605:28;;;27655:4;27648:11;;;;;;;26578:1135;27697:5;27690:12;;;;;18112:151;18187:12;18218:38;18240:6;18248:4;18254:1;18187:12;18828;18842:23;18869:6;-1:-1:-1;;;;;18869:11:0;18888:5;18895:4;18869:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18827:73;;;;18917:55;18944:6;18952:7;18961:10;18917:26;:55::i;:::-;18910:62;18587:392;-1:-1:-1;;;;;;18587:392:0:o;20032:582::-;20176:12;20205:7;20200:408;;20228:19;20236:10;20228:7;:19::i;:::-;20200:408;;;20452:17;;:22;:49;;;;-1:-1:-1;;;;;;20478:18:0;;;:23;20452:49;20448:119;;;20528:24;;;;;-1:-1:-1;;;;;7391:55:1;;20528:24:0;;;7373:74:1;7346:18;;20528:24:0;7227:226:1;20448:119:0;-1:-1:-1;20587:10:0;20580:17;;21150:516;21281:17;;:21;21277:383;;21509:10;21503:17;21565:15;21552:10;21548:2;21544:19;21537:44;21277:383;21632:17;;;;;;;;;;;;;;14:332:1;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;180:9;167:23;230:66;223:5;219:78;212:5;209:89;199:117;;312:1;309;302:12;821:180;880:6;933:2;921:9;912:7;908:23;904:32;901:52;;;949:1;946;939:12;901:52;-1:-1:-1;972:23:1;;821:180;-1:-1:-1;821:180:1:o;1006:184::-;1058:77;1055:1;1048:88;1155:4;1152:1;1145:15;1179:4;1176:1;1169:15;1195:402;1344:2;1329:18;;1377:1;1366:13;;1356:201;;1413:77;1410:1;1403:88;1514:4;1511:1;1504:15;1542:4;1539:1;1532:15;1356:201;1566:25;;;1195:402;:::o;1602:154::-;-1:-1:-1;;;;;1681:5:1;1677:54;1670:5;1667:65;1657:93;;1746:1;1743;1736:12;1761:134;1829:20;;1858:31;1829:20;1858:31;:::i;:::-;1761:134;;;:::o;1900:388::-;1968:6;1976;2029:2;2017:9;2008:7;2004:23;2000:32;1997:52;;;2045:1;2042;2035:12;1997:52;2084:9;2071:23;2103:31;2128:5;2103:31;:::i;:::-;2153:5;-1:-1:-1;2210:2:1;2195:18;;2182:32;2223:33;2182:32;2223:33;:::i;:::-;2275:7;2265:17;;;1900:388;;;;;:::o;2475:315::-;2543:6;2551;2604:2;2592:9;2583:7;2579:23;2575:32;2572:52;;;2620:1;2617;2610:12;2572:52;2656:9;2643:23;2633:33;;2716:2;2705:9;2701:18;2688:32;2729:31;2754:5;2729:31;:::i;2795:184::-;2847:77;2844:1;2837:88;2944:4;2941:1;2934:15;2968:4;2965:1;2958:15;2984:252;3056:2;3050:9;3098:3;3086:16;;3132:18;3117:34;;3153:22;;;3114:62;3111:88;;;3179:18;;:::i;:::-;3215:2;3208:22;2984:252;:::o;3241:247::-;3308:2;3302:9;3350:3;3338:16;;3384:18;3369:34;;3405:22;;;3366:62;3363:88;;;3431:18;;:::i;3493:777::-;3535:5;3588:3;3581:4;3573:6;3569:17;3565:27;3555:55;;3606:1;3603;3596:12;3555:55;3642:6;3629:20;3668:18;3705:2;3701;3698:10;3695:36;;;3711:18;;:::i;:::-;3845:2;3839:9;3907:4;3899:13;;3750:66;3895:22;;;3919:2;3891:31;3887:40;3875:53;;;3943:18;;;3963:22;;;3940:46;3937:72;;;3989:18;;:::i;:::-;4029:10;4025:2;4018:22;4064:2;4056:6;4049:18;4110:3;4103:4;4098:2;4090:6;4086:15;4082:26;4079:35;4076:55;;;4127:1;4124;4117:12;4076:55;4191:2;4184:4;4176:6;4172:17;4165:4;4157:6;4153:17;4140:54;4238:1;4231:4;4226:2;4218:6;4214:15;4210:26;4203:37;4258:6;4249:15;;;;;;3493:777;;;;:::o;4275:455::-;4352:6;4360;4413:2;4401:9;4392:7;4388:23;4384:32;4381:52;;;4429:1;4426;4419:12;4381:52;4469:9;4456:23;4502:18;4494:6;4491:30;4488:50;;;4534:1;4531;4524:12;4488:50;4557:49;4598:7;4589:6;4578:9;4574:22;4557:49;:::i;:::-;4547:59;;;4656:2;4645:9;4641:18;4628:32;4669:31;4694:5;4669:31;:::i;4735:121::-;4820:10;4813:5;4809:22;4802:5;4799:33;4789:61;;4846:1;4843;4836:12;4861:132;4928:20;;4957:30;4928:20;4957:30;:::i;4998:118::-;5084:5;5077:13;5070:21;5063:5;5060:32;5050:60;;5106:1;5103;5096:12;5121:128;5186:20;;5215:28;5186:20;5215:28;:::i;5254:865::-;5342:6;5395:3;5383:9;5374:7;5370:23;5366:33;5363:53;;;5412:1;5409;5402:12;5363:53;5438:22;;:::i;:::-;5483:28;5501:9;5483:28;:::i;:::-;5476:5;5469:43;5544:38;5578:2;5567:9;5563:18;5544:38;:::i;:::-;5539:2;5532:5;5528:14;5521:62;5615:38;5649:2;5638:9;5634:18;5615:38;:::i;:::-;5610:2;5603:5;5599:14;5592:62;5686:38;5720:2;5709:9;5705:18;5686:38;:::i;:::-;5681:2;5674:5;5670:14;5663:62;5758:39;5792:3;5781:9;5777:19;5758:39;:::i;:::-;5752:3;5745:5;5741:15;5734:64;5859:3;5848:9;5844:19;5831:33;5825:3;5818:5;5814:15;5807:58;5926:3;5915:9;5911:19;5898:33;5892:3;5885:5;5881:15;5874:58;5965:36;5996:3;5985:9;5981:19;5965:36;:::i;:::-;5959:3;5948:15;;5941:61;6021:3;6069:18;;;6056:32;6040:14;;;6033:56;;;;-1:-1:-1;5952:5:1;5254:865;-1:-1:-1;5254:865:1:o;6124:320::-;6192:6;6245:2;6233:9;6224:7;6220:23;6216:32;6213:52;;;6261:1;6258;6251:12;6213:52;6301:9;6288:23;6334:18;6326:6;6323:30;6320:50;;;6366:1;6363;6356:12;6320:50;6389:49;6430:7;6421:6;6410:9;6406:22;6389:49;:::i;:::-;6379:59;6124:320;-1:-1:-1;;;;6124:320:1:o;6449:388::-;6526:6;6534;6587:2;6575:9;6566:7;6562:23;6558:32;6555:52;;;6603:1;6600;6593:12;6555:52;6643:9;6630:23;6676:18;6668:6;6665:30;6662:50;;;6708:1;6705;6698:12;6662:50;6731:49;6772:7;6763:6;6752:9;6748:22;6731:49;:::i;:::-;6721:59;6827:2;6812:18;;;;6799:32;;-1:-1:-1;;;;6449:388:1:o;6842:248::-;6910:6;6918;6971:2;6959:9;6950:7;6946:23;6942:32;6939:52;;;6987:1;6984;6977:12;6939:52;-1:-1:-1;;7010:23:1;;;7080:2;7065:18;;;7052:32;;-1:-1:-1;6842:248:1:o;7890:1373::-;8121:13;;7867:10;7856:22;7844:35;;8090:3;8075:19;;8193:4;8185:6;8181:17;8175:24;8208:53;8255:4;8244:9;8240:20;8226:12;7867:10;7856:22;7844:35;;7791:94;8208:53;;8310:4;8302:6;8298:17;8292:24;8325:56;8375:4;8364:9;8360:20;8344:14;-1:-1:-1;;;;;7161:54:1;7149:67;;7095:127;8325:56;;8430:4;8422:6;8418:17;8412:24;8445:56;8495:4;8484:9;8480:20;8464:14;-1:-1:-1;;;;;7161:54:1;7149:67;;7095:127;8445:56;;8550:4;8542:6;8538:17;8532:24;8565:56;8615:4;8604:9;8600:20;8584:14;-1:-1:-1;;;;;7161:54:1;7149:67;;7095:127;8565:56;;8670:4;8662:6;8658:17;8652:24;8685:56;8735:4;8724:9;8720:20;8704:14;-1:-1:-1;;;;;7161:54:1;7149:67;;7095:127;8685:56;;8797:4;8789:6;8785:17;8779:24;8772:4;8761:9;8757:20;8750:54;8860:4;8852:6;8848:17;8842:24;8835:4;8824:9;8820:20;8813:54;8886:6;8946:2;8938:6;8934:15;8928:22;8923:2;8912:9;8908:18;8901:50;;8970:6;9025:2;9017:6;9013:15;9007:22;9038:51;9085:2;9074:9;9070:18;9054:14;421:13;414:21;402:34;;351:91;9038:51;-1:-1:-1;;9108:6:1;9156:15;;;9150:22;9130:18;;;9123:50;9192:6;9240:15;;;9234:22;9214:18;;;;9207:50;;;;7890:1373;:::o;9453:247::-;9512:6;9565:2;9553:9;9544:7;9540:23;9536:32;9533:52;;;9581:1;9578;9571:12;9533:52;9620:9;9607:23;9639:31;9664:5;9639:31;:::i;10108:184::-;10160:77;10157:1;10150:88;10257:4;10254:1;10247:15;10281:4;10278:1;10271:15;10297:125;10362:9;;;10383:10;;;10380:36;;;10396:18;;:::i;10729:168::-;10802:9;;;10833;;10850:15;;;10844:22;;10830:37;10820:71;;10871:18;;:::i;10902:274::-;10942:1;10968;10958:189;;11003:77;11000:1;10993:88;11104:4;11101:1;11094:15;11132:4;11129:1;11122:15;10958:189;-1:-1:-1;11161:9:1;;10902:274::o;11181:128::-;11248:9;;;11269:11;;;11266:37;;;11283:18;;:::i;11314:195::-;11353:3;11384:66;11377:5;11374:77;11371:103;;11454:18;;:::i;:::-;-1:-1:-1;11501:1:1;11490:13;;11314:195::o;11514:250::-;11599:1;11609:113;11623:6;11620:1;11617:13;11609:113;;;11699:11;;;11693:18;11680:11;;;11673:39;11645:2;11638:10;11609:113;;;-1:-1:-1;;11756:1:1;11738:16;;11731:27;11514:250::o;11769:1014::-;12076:3;12065:9;12058:22;12039:4;12109:6;12103:13;12153:6;12147:3;12136:9;12132:19;12125:35;12179:3;12191:81;12265:6;12260:2;12249:9;12245:18;12238:4;12230:6;12226:17;12191:81;:::i;:::-;12452:10;12440:23;;;;12433:4;12418:20;;12411:53;-1:-1:-1;;;;;12561:15:1;;;12556:2;12541:18;;12534:43;12613:15;;;;12608:2;12593:18;;12586:43;12660:3;12645:19;;12638:35;;;;12704:3;12689:19;;12682:35;;;;12761:14;12754:22;12748:3;12733:19;;12726:51;12324:2;12312:15;;;-1:-1:-1;12308:88:1;12293:104;12289:113;;;;;-1:-1:-1;;11769:1014:1:o;13422:136::-;13500:13;;13522:30;13500:13;13522:30;:::i;13563:138::-;13642:13;;13664:31;13642:13;13664:31;:::i;13706:132::-;13782:13;;13804:28;13782:13;13804:28;:::i;13843:1183::-;13946:6;13999:3;13987:9;13978:7;13974:23;13970:33;13967:53;;;14016:1;14013;14006:12;13967:53;14042:17;;:::i;:::-;14082:39;14111:9;14082:39;:::i;:::-;14075:5;14068:54;14154:48;14198:2;14187:9;14183:18;14154:48;:::i;:::-;14149:2;14142:5;14138:14;14131:72;14235:49;14280:2;14269:9;14265:18;14235:49;:::i;:::-;14230:2;14223:5;14219:14;14212:73;14317:49;14362:2;14351:9;14347:18;14317:49;:::i;:::-;14312:2;14305:5;14301:14;14294:73;14400:50;14445:3;14434:9;14430:19;14400:50;:::i;:::-;14394:3;14387:5;14383:15;14376:75;14484:50;14529:3;14518:9;14514:19;14484:50;:::i;:::-;14478:3;14471:5;14467:15;14460:75;14589:3;14578:9;14574:19;14568:26;14562:3;14555:5;14551:15;14544:51;14649:3;14638:9;14634:19;14628:26;14622:3;14615:5;14611:15;14604:51;14674:3;14730:2;14719:9;14715:18;14709:25;14704:2;14697:5;14693:14;14686:49;;14754:3;14789:46;14831:2;14820:9;14816:18;14789:46;:::i;:::-;14773:14;;;14766:70;14855:3;14896:18;;;14890:25;14874:14;;;14867:49;14935:3;14976:18;;;14970:25;14954:14;;;14947:49;;;;-1:-1:-1;14777:5:1;13843:1183;-1:-1:-1;13843:1183:1:o;16187:184::-;16257:6;16310:2;16298:9;16289:7;16285:23;16281:32;16278:52;;;16326:1;16323;16316:12;16278:52;-1:-1:-1;16349:16:1;;16187:184;-1:-1:-1;16187:184:1:o;16678:::-;16730:77;16727:1;16720:88;16827:4;16824:1;16817:15;16851:4;16848:1;16841:15;16867:245;16934:6;16987:2;16975:9;16966:7;16962:23;16958:32;16955:52;;;17003:1;17000;16993:12;16955:52;17035:9;17029:16;17054:28;17076:5;17054:28;:::i;17117:184::-;17169:77;17166:1;17159:88;17266:4;17263:1;17256:15;17290:4;17287:1;17280:15;17306:287;17435:3;17473:6;17467:13;17489:66;17548:6;17543:3;17536:4;17528:6;17524:17;17489:66;:::i;:::-;17571:16;;;;;17306:287;-1:-1:-1;;17306:287:1:o","abiDefinition":[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"AmountIncorrect","type":"error"},{"inputs":[],"name":"ChainIncorrect","type":"error"},{"inputs":[],"name":"DeadlineExceeded","type":"error"},{"inputs":[],"name":"DeadlineNotExceeded","type":"error"},{"inputs":[],"name":"DeadlineTooShort","type":"error"},{"inputs":[],"name":"DisputePeriodNotPassed","type":"error"},{"inputs":[],"name":"DisputePeriodPassed","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"MsgValueIncorrect","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"SenderIncorrect","type":"error"},{"inputs":[],"name":"StatusIncorrect","type":"error"},{"inputs":[],"name":"TokenNotContract","type":"error"},{"inputs":[],"name":"TransactionRelayed","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositRefunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"}],"name":"BridgeProofDisputed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":false,"internalType":"bytes32","name":"transactionHash","type":"bytes32"}],"name":"BridgeProofProvided","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint32","name":"originChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"chainGasAmount","type":"uint256"}],"name":"BridgeRelayed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes","name":"request","type":"bytes"},{"indexed":false,"internalType":"uint32","name":"destChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"sendChainGas","type":"bool"}],"name":"BridgeRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldChainGasAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"ChainGasAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFeeRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"FeeRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesSwept","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DISPUTE_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_RATE_MAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GOVERNOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GUARD_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_DEADLINE_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFUNDER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFUND_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAYER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstChainId","type":"uint32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IFastBridge.BridgeParams","name":"params","type":"tuple"}],"name":"bridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"bridgeProofs","outputs":[{"internalType":"uint96","name":"timestamp","type":"uint96"},{"internalType":"address","name":"relayer","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"bridgeRelays","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"bridgeStatuses","outputs":[{"internalType":"enum FastBridge.BridgeStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"address","name":"relayer","type":"address"}],"name":"canClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainGasAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"address","name":"to","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deployBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"dispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"getBridgeTransaction","outputs":[{"components":[{"internalType":"uint32","name":"originChainId","type":"uint32"},{"internalType":"uint32","name":"destChainId","type":"uint32"},{"internalType":"address","name":"originSender","type":"address"},{"internalType":"address","name":"destRecipient","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256","name":"originFeeAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct IFastBridge.BridgeTransaction","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"protocolFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"bytes32","name":"destTxHash","type":"bytes32"}],"name":"prove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"relay","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"setChainGasAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"setProtocolFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"sweepProtocolFees","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"DISPUTE_PERIOD()":{"notice":"Dispute period for relayed transactions"},"MIN_DEADLINE_PERIOD()":{"notice":"Minimum deadline period to relay a requested bridge transaction"},"REFUND_DELAY()":{"notice":"Delay for a transaction after which it could be permisionlessly refunded"},"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"notice":"Initiates bridge on origin chain to be relayed by off-chain relayer"},"bridgeProofs(bytes32)":{"notice":"Proof of relayed bridge tx on origin chain"},"bridgeRelays(bytes32)":{"notice":"Whether bridge has been relayed on destination chain"},"bridgeStatuses(bytes32)":{"notice":"Status of the bridge tx on origin chain"},"canClaim(bytes32,address)":{"notice":"Checks if the dispute period has passed so bridge deposit can be claimed"},"chainGasAmount()":{"notice":"Chain gas amount to forward as rebate if requested"},"claim(bytes,address)":{"notice":"Completes bridge transaction on origin chain by claiming originally deposited capital"},"dispute(bytes32)":{"notice":"Disputes an outstanding proof in case relayer provided dest chain tx is invalid"},"getBridgeTransaction(bytes)":{"notice":"Decodes bridge request into a bridge transaction"},"protocolFeeRate()":{"notice":"Protocol fee rate taken on origin amount deposited in origin chain"},"protocolFees(address)":{"notice":"Protocol fee amounts accumulated"},"prove(bytes,bytes32)":{"notice":"Provides proof on origin side that relayer provided funds on destination side of bridge transaction"},"refund(bytes)":{"notice":"Refunds an outstanding bridge transaction in case optimistic bridging failed"},"relay(bytes)":{"notice":"Relays destination side of bridge transaction by off-chain relayer"}},"version":1},"developerDoc":{"errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}],"AddressEmptyCode(address)":[{"details":"There's no code at `target` (it is not a contract)."}],"AddressInsufficientBalance(address)":[{"details":"The ETH balance of the account is not enough to perform the operation."}],"FailedInnerCall()":[{"details":"A call to an address target failed. The target may have reverted."}],"SafeERC20FailedOperation(address)":[{"details":"An operation with an ERC-20 token failed."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"params":{"params":"The parameters required to bridge"}},"canClaim(bytes32,address)":{"params":{"relayer":"The address of the relayer attempting to claim","transactionId":"The transaction id associated with the encoded bridge transaction to check"}},"claim(bytes,address)":{"params":{"request":"The encoded bridge transaction to claim on origin chain","to":"The recipient address of the funds"}},"dispute(bytes32)":{"params":{"transactionId":"The transaction id associated with the encoded bridge transaction to dispute"}},"getBridgeTransaction(bytes)":{"params":{"request":"The bridge request to decode"}},"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"getRoleMember(bytes32,uint256)":{"details":"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information."},"getRoleMemberCount(bytes32)":{"details":"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"prove(bytes,bytes32)":{"params":{"destTxHash":"The destination tx hash proving bridge transaction was relayed","request":"The encoded bridge transaction to prove on origin chain"}},"refund(bytes)":{"params":{"request":"The encoded bridge transaction to refund"}},"relay(bytes)":{"params":{"request":"The encoded bridge transaction to relay on destination chain"}},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"stateVariables":{"nonce":{"details":"to prevent replays"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineNotExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineTooShort\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputePeriodNotPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisputePeriodPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MsgValueIncorrect\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SenderIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StatusIncorrect\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenNotContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransactionRelayed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositRefunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"BridgeProofDisputed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"transactionHash\",\"type\":\"bytes32\"}],\"name\":\"BridgeProofProvided\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"BridgeRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"}],\"name\":\"BridgeRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DISPUTE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_DEADLINE_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REFUNDER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REFUND_DELAY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"bridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeProofs\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"timestamp\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeRelays\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"bridgeStatuses\",\"outputs\":[{\"internalType\":\"enum FastBridge.BridgeStatus\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"canClaim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"dispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"getBridgeTransaction\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originSender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destRecipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originFeeAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeTransaction\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"destTxHash\",\"type\":\"bytes32\"}],\"name\":\"prove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"refund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}],\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"AddressInsufficientBalance(address)\":[{\"details\":\"The ETH balance of the account is not enough to perform the operation.\"}],\"FailedInnerCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"params\":{\"params\":\"The parameters required to bridge\"}},\"canClaim(bytes32,address)\":{\"params\":{\"relayer\":\"The address of the relayer attempting to claim\",\"transactionId\":\"The transaction id associated with the encoded bridge transaction to check\"}},\"claim(bytes,address)\":{\"params\":{\"request\":\"The encoded bridge transaction to claim on origin chain\",\"to\":\"The recipient address of the funds\"}},\"dispute(bytes32)\":{\"params\":{\"transactionId\":\"The transaction id associated with the encoded bridge transaction to dispute\"}},\"getBridgeTransaction(bytes)\":{\"params\":{\"request\":\"The bridge request to decode\"}},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"getRoleMember(bytes32,uint256)\":{\"details\":\"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.\"},\"getRoleMemberCount(bytes32)\":{\"details\":\"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"prove(bytes,bytes32)\":{\"params\":{\"destTxHash\":\"The destination tx hash proving bridge transaction was relayed\",\"request\":\"The encoded bridge transaction to prove on origin chain\"}},\"refund(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to refund\"}},\"relay(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to relay on destination chain\"}},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"stateVariables\":{\"nonce\":{\"details\":\"to prevent replays\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DISPUTE_PERIOD()\":{\"notice\":\"Dispute period for relayed transactions\"},\"MIN_DEADLINE_PERIOD()\":{\"notice\":\"Minimum deadline period to relay a requested bridge transaction\"},\"REFUND_DELAY()\":{\"notice\":\"Delay for a transaction after which it could be permisionlessly refunded\"},\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"notice\":\"Initiates bridge on origin chain to be relayed by off-chain relayer\"},\"bridgeProofs(bytes32)\":{\"notice\":\"Proof of relayed bridge tx on origin chain\"},\"bridgeRelays(bytes32)\":{\"notice\":\"Whether bridge has been relayed on destination chain\"},\"bridgeStatuses(bytes32)\":{\"notice\":\"Status of the bridge tx on origin chain\"},\"canClaim(bytes32,address)\":{\"notice\":\"Checks if the dispute period has passed so bridge deposit can be claimed\"},\"chainGasAmount()\":{\"notice\":\"Chain gas amount to forward as rebate if requested\"},\"claim(bytes,address)\":{\"notice\":\"Completes bridge transaction on origin chain by claiming originally deposited capital\"},\"dispute(bytes32)\":{\"notice\":\"Disputes an outstanding proof in case relayer provided dest chain tx is invalid\"},\"getBridgeTransaction(bytes)\":{\"notice\":\"Decodes bridge request into a bridge transaction\"},\"protocolFeeRate()\":{\"notice\":\"Protocol fee rate taken on origin amount deposited in origin chain\"},\"protocolFees(address)\":{\"notice\":\"Protocol fee amounts accumulated\"},\"prove(bytes,bytes32)\":{\"notice\":\"Provides proof on origin side that relayer provided funds on destination side of bridge transaction\"},\"refund(bytes)\":{\"notice\":\"Refunds an outstanding bridge transaction in case optimistic bridging failed\"},\"relay(bytes)\":{\"notice\":\"Relays destination side of bridge transaction by off-chain relayer\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"FastBridge\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0x4fff59c4cd271340f4a824126cbe4ebe7c8dc20639e268edf42ff873af31f862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4d33ef4f98d2abd98b4bbcb403b27495c37843b37000bea9f48e533078144d84\",\"dweb:/ipfs/QmTMkQhtNJPVgpxiLnEG45Ww7xfXHMEoVQ5JdbEbaFXwwS\"]}},\"version\":1}"},"hashes":{"DEFAULT_ADMIN_ROLE()":"a217fddf","DISPUTE_PERIOD()":"a5bbe22b","FEE_BPS()":"bf333f2c","FEE_RATE_MAX()":"0f5f6ed7","GOVERNOR_ROLE()":"ccc57490","GUARD_ROLE()":"03ed0ee5","MIN_DEADLINE_PERIOD()":"820688d5","REFUNDER_ROLE()":"5960ccf2","REFUND_DELAY()":"190da595","RELAYER_ROLE()":"926d7d7f","bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":"45851694","bridgeProofs(bytes32)":"91ad5039","bridgeRelays(bytes32)":"8379a24f","bridgeStatuses(bytes32)":"051287bc","canClaim(bytes32,address)":"aa9641ab","chainGasAmount()":"e00a83e0","claim(bytes,address)":"41fcb612","deployBlock()":"a3ec191a","dispute(bytes32)":"add98c70","getBridgeTransaction(bytes)":"ac11fb1a","getRoleAdmin(bytes32)":"248a9ca3","getRoleMember(bytes32,uint256)":"9010d07c","getRoleMemberCount(bytes32)":"ca15c873","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","nonce()":"affed0e0","protocolFeeRate()":"58f85880","protocolFees(address)":"dcf844a7","prove(bytes,bytes32)":"886d36ff","refund(bytes)":"5eb7d946","relay(bytes)":"8f0d6f17","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","setChainGasAmount(uint256)":"b250fe6b","setProtocolFeeRate(uint256)":"b13aa2d6","supportsInterface(bytes4)":"01ffc9a7","sweepProtocolFees(address,address)":"06f333f2"}},"solidity/FastBridgeMock.sol:FastBridgeMock":{"code":"0x60a06040523480156200001157600080fd5b506040516200254e3803806200254e833981016040819052620000349162000194565b80620000426000826200004f565b50504360805250620001bf565b6000806200005e84846200008c565b90508015620000835760008481526001602052604090206200008190846200013a565b505b90505b92915050565b6000828152602081815260408083206001600160a01b038516845290915281205460ff1662000131576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055620000e83390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600162000086565b50600062000086565b600062000083836001600160a01b0384166000818152600183016020526040812054620001315750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000086565b600060208284031215620001a757600080fd5b81516001600160a01b03811681146200008357600080fd5b608051612373620001db600039600061053201526123736000f3fe6080604052600436106102345760003560e01c8063926d7d7f11610138578063b13aa2d6116100b0578063ca15c8731161007f578063d547741f11610064578063d547741f146106dd578063dcf844a7146106fd578063e00a83e01461072a57600080fd5b8063ca15c87314610689578063ccc57490146106a957600080fd5b8063b13aa2d614610612578063b250fe6b14610632578063bf333f2c14610652578063c72870cc1461066957600080fd5b8063ac11fb1a11610107578063add98c70116100ec578063add98c70146105c1578063aedf009d146105dc578063affed0e0146105fc57600080fd5b8063ac11fb1a14610574578063acaebbf1146105a157600080fd5b8063926d7d7f146104d7578063a217fddf1461050b578063a3ec191a14610520578063aa9641ab1461055457600080fd5b806345851694116101cb57806385ad903d1161019a5780638f0d6f171161017f5780638f0d6f17146104335780639010d07c1461044157806391d148541461048657600080fd5b806385ad903d146103eb578063886d36ff1461041857600080fd5b8063458516941461037857806358f85880146103865780635960ccf21461039c5780635eb7d946146103d057600080fd5b8063248a9ca311610207578063248a9ca3146102e85780632f2ff15d1461031857806336568abe1461033857806341fcb6121461035857600080fd5b806301ffc9a71461023957806303ed0ee51461026e57806306f333f2146102b05780630f5f6ed7146102d2575b600080fd5b34801561024557600080fd5b5061025961025436600461195d565b610740565b60405190151581526020015b60405180910390f35b34801561027a57600080fd5b506102a27f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b604051908152602001610265565b3480156102bc57600080fd5b506102d06102cb3660046119d1565b61079c565b005b3480156102de57600080fd5b506102a261271081565b3480156102f457600080fd5b506102a2610303366004611a0a565b60009081526020819052604090206001015490565b34801561032457600080fd5b506102d0610333366004611a23565b61088a565b34801561034457600080fd5b506102d0610353366004611a23565b6108b5565b34801561036457600080fd5b506102d0610373366004611b70565b61090e565b6102d0610373366004611c90565b34801561039257600080fd5b506102a260025481565b3480156103a857600080fd5b506102a27fdb9556138406326f00296e13ea2ad7db24ba82381212d816b1a40c23b466b32781565b3480156103dc57600080fd5b506102d0610373366004611cad565b3480156103f757600080fd5b5061040b610406366004611cea565b610975565b6040516102659190611d79565b34801561042457600080fd5b506102d0610373366004611d8c565b6102d0610373366004611cad565b34801561044d57600080fd5b5061046161045c366004611dd1565b610b25565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610265565b34801561049257600080fd5b506102596104a1366004611a23565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b3480156104e357600080fd5b506102a27fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b34801561051757600080fd5b506102a2600081565b34801561052c57600080fd5b506102a27f000000000000000000000000000000000000000000000000000000000000000081565b34801561056057600080fd5b5061025961056f366004611a23565b610b44565b34801561058057600080fd5b5061059461058f366004611cad565b610ba9565b6040516102659190611df3565b3480156105ad57600080fd5b506102d06105bc366004611f0d565b610c1c565b3480156105cd57600080fd5b506102d0610373366004611a0a565b3480156105e857600080fd5b506102d06105f7366004611f4d565b610dec565b34801561060857600080fd5b506102a260055481565b34801561061e57600080fd5b506102d061062d366004611a0a565b610e77565b34801561063e57600080fd5b506102d061064d366004611a0a565b610f54565b34801561065e57600080fd5b506102a2620f424081565b34801561067557600080fd5b506102d0610684366004611fa6565b610fbc565b34801561069557600080fd5b506102a26106a4366004611a0a565b611042565b3480156106b557600080fd5b506102a27f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b3480156106e957600080fd5b506102d06106f8366004611a23565b611059565b34801561070957600080fd5b506102a261071836600461203e565b60036020526000908152604090205481565b34801561073657600080fd5b506102a260045481565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f00000000000000000000000000000000000000000000000000000000148061079657506107968261107e565b92915050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556107c681611115565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812054908190036107fa5750505050565b73ffffffffffffffffffffffffffffffffffffffff841660008181526003602052604081205561082b908483611122565b6040805173ffffffffffffffffffffffffffffffffffffffff8087168252851660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b505050565b6000828152602081905260409020600101546108a581611115565b6108af8383611279565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610904576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61088582826112ae565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6e6f7420696d706c656d656e746564000000000000000000000000000000000060448201526064015b60405180910390fd5b60608160048111156109895761098961205b565b6000036109c957505060408051808201909152600481527f4e554c4c00000000000000000000000000000000000000000000000000000000602082015290565b8160048111156109db576109db61205b565b600103610a1b57505060408051808201909152600981527f5245515545535445440000000000000000000000000000000000000000000000602082015290565b816004811115610a2d57610a2d61205b565b600203610a6d57505060408051808201909152600e81527f52454c415945525f50524f564544000000000000000000000000000000000000602082015290565b816004811115610a7f57610a7f61205b565b600303610abf57505060408051808201909152600f81527f52454c415945525f434c41494d45440000000000000000000000000000000000602082015290565b816004811115610ad157610ad161205b565b600403610b1157505060408051808201909152600881527f524546554e444544000000000000000000000000000000000000000000000000602082015290565b505060408051602081019091526000815290565b6000828152600160205260408120610b3d90836112db565b9392505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6e6f7420696d706c656d656e7465640000000000000000000000000000000000604482015260009060640161096c565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201528251909161079691840181019084016120ab565b6000620f42406002548360a00151610c3491906121a6565b610c3e91906121bd565b9050808260a001818151610c5291906121f8565b9150818152505060006040518061018001604052804663ffffffff168152602001846000015163ffffffff168152602001846020015173ffffffffffffffffffffffffffffffffffffffff168152602001846040015173ffffffffffffffffffffffffffffffffffffffff168152602001846060015173ffffffffffffffffffffffffffffffffffffffff168152602001846080015173ffffffffffffffffffffffffffffffffffffffff1681526020018460a0015181526020018460c0015181526020018381526020018460e0015115158152602001846101000151815260200160056000815480929190610d479061220b565b909155509052604051610d5d9190602001611df3565b6040516020818303038152906040529050826020015173ffffffffffffffffffffffffffffffffffffffff16857f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a838660000151876060015188608001518960a001518a60c001518b60e00151604051610ddd9796959493929190612243565b60405180910390a35050505050565b6000610df782610ba9565b9050806040015173ffffffffffffffffffffffffffffffffffffffff16847f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a84846020015185608001518660a001518760c001518860e00151896101200151604051610e699796959493929190612243565b60405180910390a350505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55610ea181611115565b612710821115610f0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d617800000000000000000000000000000000604482015260640161096c565b600280549083905560408051828152602081018590527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a1505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55610f7e81611115565b600480549083905560408051828152602081018590527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa9101610f47565b6040805163ffffffff8816815273ffffffffffffffffffffffffffffffffffffffff878116602083015286811682840152606082018690526080820185905260a082018490529151898316928b16918c917ff8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c9181900360c00190a4505050505050505050565b6000818152600160205260408120610796906112e7565b60008281526020819052604090206001015461107481611115565b6108af83836112ae565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061079657507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610796565b61111f81336112f1565b50565b3073ffffffffffffffffffffffffffffffffffffffff83160361114457505050565b8060000361115157505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8416016112585760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146111e8576040519150601f19603f3d011682016040523d82523d6000602084013e6111ed565b606091505b50509050806108af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c656400000000000000000000000000604482015260640161096c565b61088573ffffffffffffffffffffffffffffffffffffffff8416838361137b565b6000806112868484611408565b90508015610b3d5760008481526001602052604090206112a69084611504565b509392505050565b6000806112bb8484611526565b90508015610b3d5760008481526001602052604090206112a690846115e1565b6000610b3d8383611603565b6000610796825490565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16611377576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024810183905260440161096c565b5050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261088590849061162d565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff166114fc5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561149a3390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610796565b506000610796565b6000610b3d8373ffffffffffffffffffffffffffffffffffffffff84166116c3565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16156114fc5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610796565b6000610b3d8373ffffffffffffffffffffffffffffffffffffffff841661170a565b600082600001828154811061161a5761161a6122a6565b9060005260206000200154905092915050565b600061164f73ffffffffffffffffffffffffffffffffffffffff8416836117fd565b9050805160001415801561167457508080602001905181019061167291906122d5565b155b15610885576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161096c565b60008181526001830160205260408120546114fc57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610796565b600081815260018301602052604081205480156117f357600061172e6001836121f8565b8554909150600090611742906001906121f8565b90508082146117a7576000866000018281548110611762576117626122a6565b9060005260206000200154905080876000018481548110611785576117856122a6565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806117b8576117b86122f2565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610796565b6000915050610796565b6060610b3d83836000846000808573ffffffffffffffffffffffffffffffffffffffff1684866040516118309190612321565b60006040518083038185875af1925050503d806000811461186d576040519150601f19603f3d011682016040523d82523d6000602084013e611872565b606091505b509150915061188286838361188c565b9695505050505050565b6060826118a15761189c8261191b565b610b3d565b81511580156118c5575073ffffffffffffffffffffffffffffffffffffffff84163b155b15611914576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015260240161096c565b5080610b3d565b80511561192b5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561196f57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610b3d57600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461111f57600080fd5b80356119cc8161199f565b919050565b600080604083850312156119e457600080fd5b82356119ef8161199f565b915060208301356119ff8161199f565b809150509250929050565b600060208284031215611a1c57600080fd5b5035919050565b60008060408385031215611a3657600080fd5b8235915060208301356119ff8161199f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715611a9b57611a9b611a48565b60405290565b604051610180810167ffffffffffffffff81118282101715611a9b57611a9b611a48565b600082601f830112611ad657600080fd5b813567ffffffffffffffff80821115611af157611af1611a48565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611b3757611b37611a48565b81604052838152866020858801011115611b5057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215611b8357600080fd5b823567ffffffffffffffff811115611b9a57600080fd5b611ba685828601611ac5565b92505060208301356119ff8161199f565b63ffffffff8116811461111f57600080fd5b80356119cc81611bb7565b801515811461111f57600080fd5b80356119cc81611bd4565b60006101208284031215611c0057600080fd5b611c08611a77565b9050611c1382611bc9565b8152611c21602083016119c1565b6020820152611c32604083016119c1565b6040820152611c43606083016119c1565b6060820152611c54608083016119c1565b608082015260a082013560a082015260c082013560c0820152611c7960e08301611be2565b60e082015261010080830135818301525092915050565b60006101208284031215611ca357600080fd5b610b3d8383611bed565b600060208284031215611cbf57600080fd5b813567ffffffffffffffff811115611cd657600080fd5b611ce284828501611ac5565b949350505050565b600060208284031215611cfc57600080fd5b813560058110610b3d57600080fd5b60005b83811015611d26578181015183820152602001611d0e565b50506000910152565b60008151808452611d47816020860160208601611d0b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610b3d6020830184611d2f565b60008060408385031215611d9f57600080fd5b823567ffffffffffffffff811115611db657600080fd5b611dc285828601611ac5565b95602094909401359450505050565b60008060408385031215611de457600080fd5b50508035926020909101359150565b815163ffffffff16815261018081016020830151611e19602084018263ffffffff169052565b506040830151611e41604084018273ffffffffffffffffffffffffffffffffffffffff169052565b506060830151611e69606084018273ffffffffffffffffffffffffffffffffffffffff169052565b506080830151611e91608084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060a0830151611eb960a084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c083015160c083015260e083015160e083015261010080840151818401525061012080840151611eee8285018215159052565b5050610140838101519083015261016092830151929091019190915290565b60008060006101608486031215611f2357600080fd5b833592506020840135611f358161199f565b9150611f448560408601611bed565b90509250925092565b600080600060608486031215611f6257600080fd5b833592506020840135611f748161199f565b9150604084013567ffffffffffffffff811115611f9057600080fd5b611f9c86828701611ac5565b9150509250925092565b60008060008060008060008060006101208a8c031215611fc557600080fd5b8935985060208a0135611fd78161199f565b975060408a0135611fe78161199f565b965060608a0135611ff781611bb7565b955060808a01356120078161199f565b945060a08a01356120178161199f565b8094505060c08a0135925060e08a013591506101008a013590509295985092959850929598565b60006020828403121561205057600080fd5b8135610b3d8161199f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b80516119cc81611bb7565b80516119cc8161199f565b80516119cc81611bd4565b600061018082840312156120be57600080fd5b6120c6611aa1565b6120cf8361208a565b81526120dd6020840161208a565b60208201526120ee60408401612095565b60408201526120ff60608401612095565b606082015261211060808401612095565b608082015261212160a08401612095565b60a082015260c083015160c082015260e083015160e08201526101008084015181830152506101206121548185016120a0565b908201526101408381015190820152610160928301519281019290925250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761079657610796612177565b6000826121f3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561079657610796612177565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361223c5761223c612177565b5060010190565b60e08152600061225660e083018a611d2f565b63ffffffff9890981660208301525073ffffffffffffffffffffffffffffffffffffffff9586166040820152939094166060840152608083019190915260a082015290151560c090910152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156122e757600080fd5b8151610b3d81611bd4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612333818460208701611d0b565b919091019291505056fea264697066735822122033e24b6f39317f0eea840aab6ee071e2b648a79ea7849efa62c112cddf55815d64736f6c63430008140033","runtime-code":"0x6080604052600436106102345760003560e01c8063926d7d7f11610138578063b13aa2d6116100b0578063ca15c8731161007f578063d547741f11610064578063d547741f146106dd578063dcf844a7146106fd578063e00a83e01461072a57600080fd5b8063ca15c87314610689578063ccc57490146106a957600080fd5b8063b13aa2d614610612578063b250fe6b14610632578063bf333f2c14610652578063c72870cc1461066957600080fd5b8063ac11fb1a11610107578063add98c70116100ec578063add98c70146105c1578063aedf009d146105dc578063affed0e0146105fc57600080fd5b8063ac11fb1a14610574578063acaebbf1146105a157600080fd5b8063926d7d7f146104d7578063a217fddf1461050b578063a3ec191a14610520578063aa9641ab1461055457600080fd5b806345851694116101cb57806385ad903d1161019a5780638f0d6f171161017f5780638f0d6f17146104335780639010d07c1461044157806391d148541461048657600080fd5b806385ad903d146103eb578063886d36ff1461041857600080fd5b8063458516941461037857806358f85880146103865780635960ccf21461039c5780635eb7d946146103d057600080fd5b8063248a9ca311610207578063248a9ca3146102e85780632f2ff15d1461031857806336568abe1461033857806341fcb6121461035857600080fd5b806301ffc9a71461023957806303ed0ee51461026e57806306f333f2146102b05780630f5f6ed7146102d2575b600080fd5b34801561024557600080fd5b5061025961025436600461195d565b610740565b60405190151581526020015b60405180910390f35b34801561027a57600080fd5b506102a27f043c983c49d46f0e102151eaf8085d4a2e6571d5df2d47b013f39bddfd4a639d81565b604051908152602001610265565b3480156102bc57600080fd5b506102d06102cb3660046119d1565b61079c565b005b3480156102de57600080fd5b506102a261271081565b3480156102f457600080fd5b506102a2610303366004611a0a565b60009081526020819052604090206001015490565b34801561032457600080fd5b506102d0610333366004611a23565b61088a565b34801561034457600080fd5b506102d0610353366004611a23565b6108b5565b34801561036457600080fd5b506102d0610373366004611b70565b61090e565b6102d0610373366004611c90565b34801561039257600080fd5b506102a260025481565b3480156103a857600080fd5b506102a27fdb9556138406326f00296e13ea2ad7db24ba82381212d816b1a40c23b466b32781565b3480156103dc57600080fd5b506102d0610373366004611cad565b3480156103f757600080fd5b5061040b610406366004611cea565b610975565b6040516102659190611d79565b34801561042457600080fd5b506102d0610373366004611d8c565b6102d0610373366004611cad565b34801561044d57600080fd5b5061046161045c366004611dd1565b610b25565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610265565b34801561049257600080fd5b506102596104a1366004611a23565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b3480156104e357600080fd5b506102a27fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b34801561051757600080fd5b506102a2600081565b34801561052c57600080fd5b506102a27f000000000000000000000000000000000000000000000000000000000000000081565b34801561056057600080fd5b5061025961056f366004611a23565b610b44565b34801561058057600080fd5b5061059461058f366004611cad565b610ba9565b6040516102659190611df3565b3480156105ad57600080fd5b506102d06105bc366004611f0d565b610c1c565b3480156105cd57600080fd5b506102d0610373366004611a0a565b3480156105e857600080fd5b506102d06105f7366004611f4d565b610dec565b34801561060857600080fd5b506102a260055481565b34801561061e57600080fd5b506102d061062d366004611a0a565b610e77565b34801561063e57600080fd5b506102d061064d366004611a0a565b610f54565b34801561065e57600080fd5b506102a2620f424081565b34801561067557600080fd5b506102d0610684366004611fa6565b610fbc565b34801561069557600080fd5b506102a26106a4366004611a0a565b611042565b3480156106b557600080fd5b506102a27f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f5581565b3480156106e957600080fd5b506102d06106f8366004611a23565b611059565b34801561070957600080fd5b506102a261071836600461203e565b60036020526000908152604090205481565b34801561073657600080fd5b506102a260045481565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f00000000000000000000000000000000000000000000000000000000148061079657506107968261107e565b92915050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f556107c681611115565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812054908190036107fa5750505050565b73ffffffffffffffffffffffffffffffffffffffff841660008181526003602052604081205561082b908483611122565b6040805173ffffffffffffffffffffffffffffffffffffffff8087168252851660208201529081018290527f244e51bc38c1452fa8aaf487bcb4bca36c2baa3a5fbdb776b1eabd8dc6d277cd9060600160405180910390a1505b505050565b6000828152602081905260409020600101546108a581611115565b6108af8383611279565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610904576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61088582826112ae565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6e6f7420696d706c656d656e746564000000000000000000000000000000000060448201526064015b60405180910390fd5b60608160048111156109895761098961205b565b6000036109c957505060408051808201909152600481527f4e554c4c00000000000000000000000000000000000000000000000000000000602082015290565b8160048111156109db576109db61205b565b600103610a1b57505060408051808201909152600981527f5245515545535445440000000000000000000000000000000000000000000000602082015290565b816004811115610a2d57610a2d61205b565b600203610a6d57505060408051808201909152600e81527f52454c415945525f50524f564544000000000000000000000000000000000000602082015290565b816004811115610a7f57610a7f61205b565b600303610abf57505060408051808201909152600f81527f52454c415945525f434c41494d45440000000000000000000000000000000000602082015290565b816004811115610ad157610ad161205b565b600403610b1157505060408051808201909152600881527f524546554e444544000000000000000000000000000000000000000000000000602082015290565b505060408051602081019091526000815290565b6000828152600160205260408120610b3d90836112db565b9392505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6e6f7420696d706c656d656e7465640000000000000000000000000000000000604482015260009060640161096c565b604080516101808101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101608201528251909161079691840181019084016120ab565b6000620f42406002548360a00151610c3491906121a6565b610c3e91906121bd565b9050808260a001818151610c5291906121f8565b9150818152505060006040518061018001604052804663ffffffff168152602001846000015163ffffffff168152602001846020015173ffffffffffffffffffffffffffffffffffffffff168152602001846040015173ffffffffffffffffffffffffffffffffffffffff168152602001846060015173ffffffffffffffffffffffffffffffffffffffff168152602001846080015173ffffffffffffffffffffffffffffffffffffffff1681526020018460a0015181526020018460c0015181526020018381526020018460e0015115158152602001846101000151815260200160056000815480929190610d479061220b565b909155509052604051610d5d9190602001611df3565b6040516020818303038152906040529050826020015173ffffffffffffffffffffffffffffffffffffffff16857f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a838660000151876060015188608001518960a001518a60c001518b60e00151604051610ddd9796959493929190612243565b60405180910390a35050505050565b6000610df782610ba9565b9050806040015173ffffffffffffffffffffffffffffffffffffffff16847f120ea0364f36cdac7983bcfdd55270ca09d7f9b314a2ebc425a3b01ab1d6403a84846020015185608001518660a001518760c001518860e00151896101200151604051610e699796959493929190612243565b60405180910390a350505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55610ea181611115565b612710821115610f0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6e657746656552617465203e206d617800000000000000000000000000000000604482015260640161096c565b600280549083905560408051828152602081018590527f14914da2bf76024616fbe1859783fcd4dbddcb179b1f3a854949fbf920dcb95791015b60405180910390a1505050565b7f7935bd0ae54bc31f548c14dba4d37c5c64b3f8ca900cb468fb8abd54d5894f55610f7e81611115565b600480549083905560408051828152602081018590527f5cf09b12f3f56b4c564d51b25b40360af6d795198adb61ae0806a36c294323fa9101610f47565b6040805163ffffffff8816815273ffffffffffffffffffffffffffffffffffffffff878116602083015286811682840152606082018690526080820185905260a082018490529151898316928b16918c917ff8ae392d784b1ea5e8881bfa586d81abf07ef4f1e2fc75f7fe51c90f05199a5c9181900360c00190a4505050505050505050565b6000818152600160205260408120610796906112e7565b60008281526020819052604090206001015461107481611115565b6108af83836112ae565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061079657507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610796565b61111f81336112f1565b50565b3073ffffffffffffffffffffffffffffffffffffffff83160361114457505050565b8060000361115157505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8416016112585760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146111e8576040519150601f19603f3d011682016040523d82523d6000602084013e6111ed565b606091505b50509050806108af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f455448207472616e73666572206661696c656400000000000000000000000000604482015260640161096c565b61088573ffffffffffffffffffffffffffffffffffffffff8416838361137b565b6000806112868484611408565b90508015610b3d5760008481526001602052604090206112a69084611504565b509392505050565b6000806112bb8484611526565b90508015610b3d5760008481526001602052604090206112a690846115e1565b6000610b3d8383611603565b6000610796825490565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16611377576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024810183905260440161096c565b5050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261088590849061162d565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff166114fc5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561149a3390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610796565b506000610796565b6000610b3d8373ffffffffffffffffffffffffffffffffffffffff84166116c3565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16156114fc5760008381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610796565b6000610b3d8373ffffffffffffffffffffffffffffffffffffffff841661170a565b600082600001828154811061161a5761161a6122a6565b9060005260206000200154905092915050565b600061164f73ffffffffffffffffffffffffffffffffffffffff8416836117fd565b9050805160001415801561167457508080602001905181019061167291906122d5565b155b15610885576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161096c565b60008181526001830160205260408120546114fc57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610796565b600081815260018301602052604081205480156117f357600061172e6001836121f8565b8554909150600090611742906001906121f8565b90508082146117a7576000866000018281548110611762576117626122a6565b9060005260206000200154905080876000018481548110611785576117856122a6565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806117b8576117b86122f2565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610796565b6000915050610796565b6060610b3d83836000846000808573ffffffffffffffffffffffffffffffffffffffff1684866040516118309190612321565b60006040518083038185875af1925050503d806000811461186d576040519150601f19603f3d011682016040523d82523d6000602084013e611872565b606091505b509150915061188286838361188c565b9695505050505050565b6060826118a15761189c8261191b565b610b3d565b81511580156118c5575073ffffffffffffffffffffffffffffffffffffffff84163b155b15611914576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015260240161096c565b5080610b3d565b80511561192b5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561196f57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610b3d57600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461111f57600080fd5b80356119cc8161199f565b919050565b600080604083850312156119e457600080fd5b82356119ef8161199f565b915060208301356119ff8161199f565b809150509250929050565b600060208284031215611a1c57600080fd5b5035919050565b60008060408385031215611a3657600080fd5b8235915060208301356119ff8161199f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715611a9b57611a9b611a48565b60405290565b604051610180810167ffffffffffffffff81118282101715611a9b57611a9b611a48565b600082601f830112611ad657600080fd5b813567ffffffffffffffff80821115611af157611af1611a48565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611b3757611b37611a48565b81604052838152866020858801011115611b5057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215611b8357600080fd5b823567ffffffffffffffff811115611b9a57600080fd5b611ba685828601611ac5565b92505060208301356119ff8161199f565b63ffffffff8116811461111f57600080fd5b80356119cc81611bb7565b801515811461111f57600080fd5b80356119cc81611bd4565b60006101208284031215611c0057600080fd5b611c08611a77565b9050611c1382611bc9565b8152611c21602083016119c1565b6020820152611c32604083016119c1565b6040820152611c43606083016119c1565b6060820152611c54608083016119c1565b608082015260a082013560a082015260c082013560c0820152611c7960e08301611be2565b60e082015261010080830135818301525092915050565b60006101208284031215611ca357600080fd5b610b3d8383611bed565b600060208284031215611cbf57600080fd5b813567ffffffffffffffff811115611cd657600080fd5b611ce284828501611ac5565b949350505050565b600060208284031215611cfc57600080fd5b813560058110610b3d57600080fd5b60005b83811015611d26578181015183820152602001611d0e565b50506000910152565b60008151808452611d47816020860160208601611d0b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610b3d6020830184611d2f565b60008060408385031215611d9f57600080fd5b823567ffffffffffffffff811115611db657600080fd5b611dc285828601611ac5565b95602094909401359450505050565b60008060408385031215611de457600080fd5b50508035926020909101359150565b815163ffffffff16815261018081016020830151611e19602084018263ffffffff169052565b506040830151611e41604084018273ffffffffffffffffffffffffffffffffffffffff169052565b506060830151611e69606084018273ffffffffffffffffffffffffffffffffffffffff169052565b506080830151611e91608084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060a0830151611eb960a084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c083015160c083015260e083015160e083015261010080840151818401525061012080840151611eee8285018215159052565b5050610140838101519083015261016092830151929091019190915290565b60008060006101608486031215611f2357600080fd5b833592506020840135611f358161199f565b9150611f448560408601611bed565b90509250925092565b600080600060608486031215611f6257600080fd5b833592506020840135611f748161199f565b9150604084013567ffffffffffffffff811115611f9057600080fd5b611f9c86828701611ac5565b9150509250925092565b60008060008060008060008060006101208a8c031215611fc557600080fd5b8935985060208a0135611fd78161199f565b975060408a0135611fe78161199f565b965060608a0135611ff781611bb7565b955060808a01356120078161199f565b945060a08a01356120178161199f565b8094505060c08a0135925060e08a013591506101008a013590509295985092959850929598565b60006020828403121561205057600080fd5b8135610b3d8161199f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b80516119cc81611bb7565b80516119cc8161199f565b80516119cc81611bd4565b600061018082840312156120be57600080fd5b6120c6611aa1565b6120cf8361208a565b81526120dd6020840161208a565b60208201526120ee60408401612095565b60408201526120ff60608401612095565b606082015261211060808401612095565b608082015261212160a08401612095565b60a082015260c083015160c082015260e083015160e08201526101008084015181830152506101206121548185016120a0565b908201526101408381015190820152610160928301519281019290925250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761079657610796612177565b6000826121f3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561079657610796612177565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361223c5761223c612177565b5060010190565b60e08152600061225660e083018a611d2f565b63ffffffff9890981660208301525073ffffffffffffffffffffffffffffffffffffffff9586166040820152939094166060840152608083019190915260a082015290151560c090910152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156122e757600080fd5b8151610b3d81611bd4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612333818460208701611d0b565b919091019291505056fea264697066735822122033e24b6f39317f0eea840aab6ee071e2b648a79ea7849efa62c112cddf55815d64736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n )\n external\n {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"69539:4359:0:-:0;;;69685:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69719:6;57196:38;46368:4;69719:6;57196:10;:38::i;:::-;-1:-1:-1;;69751:12:0::1;69737:26;::::0;-1:-1:-1;69539:4359:0;;55681:257;55767:4;;55798:31;55815:4;55821:7;55798:16;:31::i;:::-;55783:46;;55843:7;55839:69;;;55866:18;;;;:12;:18;;;;;:31;;55889:7;55866:22;:31::i;:::-;;55839:69;55924:7;-1:-1:-1;55681:257:0;;;;;:::o;50315:316::-;50392:4;47090:12;;;;;;;;;;;-1:-1:-1;;;;;47090:29:0;;;;;;;;;;;;50408:217;;50451:6;:12;;;;;;;;;;;-1:-1:-1;;;;;50451:29:0;;;;;;;;;:36;;-1:-1:-1;;50451:36:0;50483:4;50451:36;;;50533:12;22406:10;;22327:96;50533:12;-1:-1:-1;;;;;50506:40:0;50524:7;-1:-1:-1;;;;;50506:40:0;50518:4;50506:40;;;;;;;;;;-1:-1:-1;50567:4:0;50560:11;;50408:217;-1:-1:-1;50609:5:0;50602:12;;31852:150;31922:4;31945:50;31950:3;-1:-1:-1;;;;;31970:23:0;;25840:4;27896:21;;;:14;;;:21;;;;;;25856:321;;-1:-1:-1;25898:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;26080:18;;26056:21;;;:14;;;:21;;;;;;:42;;;;26112:11;;14:290:1;84:6;137:2;125:9;116:7;112:23;108:32;105:52;;;153:1;150;143:12;105:52;179:16;;-1:-1:-1;;;;;224:31:1;;214:42;;204:70;;270:1;267;260:12;14:290;69539:4359:0;;;;;;;;;;;;","srcMapRuntime":"69539:4359:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54341:212;;;;;;;;;;-1:-1:-1;54341:212:0;;;;;:::i;:::-;;:::i;:::-;;;612:14:1;;605:22;587:41;;575:2;560:18;54341:212:0;;;;;;;;56571:60;;;;;;;;;;;;56608:23;56571:60;;;;;785:25:1;;;773:2;758:18;56571:60:0;639:177:1;57543:359:0;;;;;;;;;;-1:-1:-1;57543:359:0;;;;;:::i;:::-;;:::i;:::-;;56753:45;;;;;;;;;;;;56792:6;56753:45;;47946:120;;;;;;;;;;-1:-1:-1;47946:120:0;;;;;:::i;:::-;48011:7;48037:12;;;;;;;;;;:22;;;;47946:120;48362:136;;;;;;;;;;-1:-1:-1;48362:136:0;;;;;:::i;:::-;;:::i;49464:245::-;;;;;;;;;;-1:-1:-1;49464:245:0;;;;;:::i;:::-;;:::i;73604:100::-;;;;;;;;;;-1:-1:-1;73604:100:0;;;;;:::i;:::-;;:::i;73144:103::-;;;;;;:::i;56915:30::-;;;;;;;;;;;;;;;;56499:66;;;;;;;;;;;;56539:26;56499:66;;73807:89;;;;;;;;;;-1:-1:-1;73807:89:0;;;;;:::i;70322:528::-;;;;;;;;;;-1:-1:-1;70322:528:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;73355:108::-;;;;;;;;;;-1:-1:-1;73355:108:0;;;;;:::i;73253:96::-;;;;;;:::i;55138:142::-;;;;;;;;;;-1:-1:-1;55138:142:0;;;;;:::i;:::-;;:::i;:::-;;;8086:42:1;8074:55;;;8056:74;;8044:2;8029:18;55138:142:0;7910:226:1;46990:136:0;;;;;;;;;;-1:-1:-1;46990:136:0;;;;;:::i;:::-;47067:4;47090:12;;;;;;;;;;;:29;;;;;;;;;;;;;;;;46990:136;56429:64;;;;;;;;;;;;56468:25;56429:64;;46323:49;;;;;;;;;;-1:-1:-1;46323:49:0;46368:4;46323:49;;69642:36;;;;;;;;;;;;;;;73469:129;;;;;;;;;;-1:-1:-1;73469:129:0;;;;;:::i;:::-;;:::i;69835:163::-;;;;;;;;;;-1:-1:-1;69835:163:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;70856:1266::-;;;;;;;;;;-1:-1:-1;70856:1266:0;;;;;:::i;:::-;;:::i;73710:91::-;;;;;;;;;;-1:-1:-1;73710:91:0;;;;;:::i;72128:532::-;;;;;;;;;;-1:-1:-1;72128:532:0;;;;;:::i;:::-;;:::i;69808:20::-;;;;;;;;;;;;;;;;57247:290;;;;;;;;;;-1:-1:-1;57247:290:0;;;;;:::i;:::-;;:::i;57908:264::-;;;;;;;;;;-1:-1:-1;57908:264:0;;;;;:::i;:::-;;:::i;56710:37::-;;;;;;;;;;;;56744:3;56710:37;;72666:472;;;;;;;;;;-1:-1:-1;72666:472:0;;;;;:::i;:::-;;:::i;55448:131::-;;;;;;;;;;-1:-1:-1;55448:131:0;;;;;:::i;:::-;;:::i;56637:66::-;;;;;;;;;;;;56677:26;56637:66;;48778:138;;;;;;;;;;-1:-1:-1;48778:138:0;;;;;:::i;:::-;;:::i;57001:47::-;;;;;;;;;;-1:-1:-1;57001:47:0;;;;;:::i;:::-;;;;;;;;;;;;;;57122:29;;;;;;;;;;;;;;;;54341:212;54426:4;54449:57;;;54464:42;54449:57;;:97;;;54510:36;54534:11;54510:23;:36::i;:::-;54442:104;54341:212;-1:-1:-1;;54341:212:0:o;57543:359::-;56677:26;46600:16;46611:4;46600:10;:16::i;:::-;57667:19:::1;::::0;::::1;57647:17;57667:19:::0;;;:12:::1;:19;::::0;;;;;;57700:14;;;57696:27:::1;;57716:7;57543:359:::0;;;:::o;57696:27::-:1;57764:19;::::0;::::1;57786:1;57764:19:::0;;;:12:::1;:19;::::0;;;;:23;57797:45:::1;::::0;57821:9;57832;57797:23:::1;:45::i;:::-;57857:38;::::0;;12332:42:1;12401:15;;;12383:34;;12453:15;;12448:2;12433:18;;12426:43;12485:18;;;12478:34;;;57857:38:0::1;::::0;12310:2:1;12295:18;57857:38:0::1;;;;;;;57637:265;46626:1;57543:359:::0;;;:::o;48362:136::-;48011:7;48037:12;;;;;;;;;;:22;;;46600:16;46611:4;46600:10;:16::i;:::-;48466:25:::1;48477:4;48483:7;48466:10;:25::i;:::-;;48362:136:::0;;;:::o;49464:245::-;49557:34;;;22406:10;49557:34;49553:102;;49614:30;;;;;;;;;;;;;;49553:102;49665:37;49677:4;49683:18;49665:11;:37::i;73604:100::-;73672:25;;;;;12725:2:1;73672:25:0;;;12707:21:1;12764:2;12744:18;;;12737:30;12803:17;12783:18;;;12776:45;12838:18;;73672:25:0;;;;;;;;70322:528;70404:13;70465:8;70433:40;;;;;;;;:::i;:::-;:28;:40;70429:59;;-1:-1:-1;;70475:13:0;;;;;;;;;;;;;;;;;;70322:528::o;70429:59::-;70539:8;70502:45;;;;;;;;:::i;:::-;:33;:45;70498:69;;-1:-1:-1;;70549:18:0;;;;;;;;;;;;;;;;;;70322:528::o;70498:69::-;70623:8;70581:50;;;;;;;;:::i;:::-;:38;:50;70577:79;;-1:-1:-1;;70633:23:0;;;;;;;;;;;;;;;;;;70322:528::o;70577:79::-;70713:8;70670:51;;;;;;;;:::i;:::-;:39;:51;70666:81;;-1:-1:-1;;70723:24:0;;;;;;;;;;;;;;;;;;70322:528::o;70666:81::-;70797:8;70761:44;;;;;;;;:::i;:::-;:32;:44;70757:67;;-1:-1:-1;;70807:17:0;;;;;;;;;;;;;;;;;;70322:528::o;70757:67::-;-1:-1:-1;;70834:9:0;;;;;;;;;-1:-1:-1;70834:9:0;;;70322:528::o;55138:142::-;55219:7;55245:18;;;:12;:18;;;;;:28;;55267:5;55245:21;:28::i;:::-;55238:35;55138:142;-1:-1:-1;;;55138:142:0:o;73469:129::-;73566:25;;;;;12725:2:1;73566:25:0;;;12707:21:1;12764:2;12744:18;;;12737:30;12803:17;12783:18;;;12776:45;73550:4:0;;12838:18:1;;73566:25:0;12523:339:1;69835:163:0;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69951:40:0;;-1:-1:-1;;69951:40:0;;;;;;;;;;:::i;70856:1266::-;70969:23;56744:3;71018:15;;70996:6;:19;;;:37;;;;:::i;:::-;70995:49;;;;:::i;:::-;70969:75;;71077:15;71054:6;:19;;:38;;;;;;;:::i;:::-;;;;;;;;71103:20;71150:649;;;;;;;;71208:13;71150:649;;;;;;71253:6;:17;;;71150:649;;;;;;71302:6;:13;;;71150:649;;;;;;71348:6;:9;;;71150:649;;;;;;71388:6;:18;;;71150:649;;;;;;71435:6;:16;;;71150:649;;;;;;71483:6;:19;;;71150:649;;;;71556:6;:17;;;71150:649;;;;71608:15;71150:649;;;;71655:6;:19;;;71150:649;;;;;;71702:6;:15;;;71150:649;;;;71742:5;;:7;;;;;;;;;:::i;:::-;;;;-1:-1:-1;71150:649:0;;71126:683;;;;;;;;:::i;:::-;;;;;;;;;;;;;71103:706;;71881:6;:13;;;71825:290;;71854:13;71825:290;71908:7;71929:6;:17;;;71960:6;:18;;;71992:6;:16;;;72022:6;:19;;;72055:6;:17;;;72086:6;:19;;;71825:290;;;;;;;;;;;;:::i;:::-;;;;;;;;70959:1163;;70856:1266;;;:::o;72128:532::-;72238:36;72277:29;72298:7;72277:20;:29::i;:::-;72238:68;;72377:11;:24;;;72321:332;;72350:13;72321:332;72415:7;72436:11;:23;;;72473:11;:23;;;72510:11;:21;;;72545:11;:24;;;72583:11;:22;;;72619:11;:24;;;72321:332;;;;;;;;;;;;:::i;:::-;;;;;;;;72228:432;72128:532;;;:::o;57247:290::-;56677:26;46600:16;46611:4;46600:10;:16::i;:::-;56792:6:::1;57346:10;:26;;57338:55;;;::::0;::::1;::::0;;16599:2:1;57338:55:0::1;::::0;::::1;16581:21:1::0;16638:2;16618:18;;;16611:30;16677:18;16657;;;16650:46;16713:18;;57338:55:0::1;16397:340:1::0;57338:55:0::1;57424:15;::::0;;57449:28;;;;57492:38:::1;::::0;;16916:25:1;;;16972:2;16957:18;;16950:34;;;57492:38:0::1;::::0;16889:18:1;57492:38:0::1;;;;;;;;57328:209;57247:290:::0;;:::o;57908:264::-;56677:26;46600:16;46611:4;46600:10;:16::i;:::-;58033:14:::1;::::0;;58057:34;;;;58106:59:::1;::::0;;16916:25:1;;;16972:2;16957:18;;16950:34;;;58106:59:0::1;::::0;16889:18:1;58106:59:0::1;16742:248:1::0;72666:472:0;72987:144;;;17310:10:1;17298:23;;17280:42;;72987:144:0;17419:15:1;;;17414:2;17399:18;;17392:43;17471:15;;;17451:18;;;17444:43;17518:2;17503:18;;17496:34;;;17561:3;17546:19;;17539:35;;;17605:3;17590:19;;17583:35;;;72987:144:0;;;;;;;;;73014:13;;72987:144;;;;;17267:3:1;72987:144:0;;;72666:472;;;;;;;;;:::o;55448:131::-;55519:7;55545:18;;;:12;:18;;;;;:27;;:25;:27::i;48778:138::-;48011:7;48037:12;;;;;;;;;;:22;;;46600:16;46611:4;46600:10;:16::i;:::-;48883:26:::1;48895:4;48901:7;48883:11;:26::i;46701:202::-:0;46786:4;46809:47;;;46824:32;46809:47;;:87;;-1:-1:-1;38614:25:0;38599:40;;;;46860:36;38500:146;47335:103;47401:30;47412:4;22406:10;47401;:30::i;:::-;47335:103;:::o;51613:653::-;51788:4;51774:19;;;;51770:32;;51613:653;;;:::o;51770:32::-;51874:5;51883:1;51874:10;51870:23;;51613:653;;;:::o;51870:23::-;51906:20;;;;;51902:358;;52086:12;52103:2;:7;;52118:5;52103:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52085:43;;;52150:7;52142:39;;;;;;;18041:2:1;52142:39:0;;;18023:21:1;18080:2;18060:18;;;18053:30;18119:21;18099:18;;;18092:49;18158:18;;52142:39:0;17839:343:1;51902:358:0;52212:37;:26;;;52239:2;52243:5;52212:26;:37::i;55681:257::-;55767:4;55783:12;55798:31;55815:4;55821:7;55798:16;:31::i;:::-;55783:46;;55843:7;55839:69;;;55866:18;;;;:12;:18;;;;;:31;;55889:7;55866:22;:31::i;:::-;;55924:7;55681:257;-1:-1:-1;;;55681:257:0:o;56041:262::-;56128:4;56144:12;56159:32;56177:4;56183:7;56159:17;:32::i;:::-;56144:47;;56205:7;56201:72;;;56228:18;;;;:12;:18;;;;;:34;;56254:7;56228:25;:34::i;33110:156::-;33184:7;33234:22;33238:3;33250:5;33234:3;:22::i;32653:115::-;32716:7;32742:19;32750:3;28092:18;;28010:107;47568:197;47067:4;47090:12;;;;;;;;;;;:29;;;;;;;;;;;;;47651:108;;47701:47;;;;;18391:42:1;18379:55;;47701:47:0;;;18361:74:1;18451:18;;;18444:34;;;18334:18;;47701:47:0;18187:297:1;47651:108:0;47568:197;;:::o;39818:160::-;39927:43;;;39942:14;18379:55:1;;39927:43:0;;;18361:74:1;18451:18;;;;18444:34;;;39927:43:0;;;;;;;;;;18334:18:1;;;;39927:43:0;;;;;;;;;;;;;;39900:71;;39920:5;;39900:19;:71::i;50315:316::-;50392:4;47090:12;;;;;;;;;;;:29;;;;;;;;;;;;;50408:217;;50451:6;:12;;;;;;;;;;;:29;;;;;;;;;;:36;;;;50483:4;50451:36;;;50533:12;22406:10;;22327:96;50533:12;50506:40;;50524:7;50506:40;;50518:4;50506:40;;;;;;;;;;-1:-1:-1;50567:4:0;50560:11;;50408:217;-1:-1:-1;50609:5:0;50602:12;;31852:150;31922:4;31945:50;31950:3;31970:23;;;31945:4;:50::i;50866:317::-;50944:4;47090:12;;;;;;;;;;;:29;;;;;;;;;;;;;50960:217;;;51034:5;51002:12;;;;;;;;;;;:29;;;;;;;;;;;:37;;;;;;51058:40;22406:10;;51002:12;;51058:40;;51034:5;51058:40;-1:-1:-1;51119:4:0;51112:11;;32170:156;32243:4;32266:53;32274:3;32294:23;;;32266:7;:53::i;28459:118::-;28526:7;28552:3;:11;;28564:5;28552:18;;;;;;;;:::i;:::-;;;;;;;;;28545:25;;28459:118;;;;:::o;42574:629::-;42993:23;43019:33;:27;;;43047:4;43019:27;:33::i;:::-;42993:59;;43066:10;:17;43087:1;43066:22;;:57;;;;;43104:10;43093:30;;;;;;;;;;;;:::i;:::-;43092:31;43066:57;43062:135;;;43146:40;;;;;8086:42:1;8074:55;;43146:40:0;;;8056:74:1;8029:18;;43146:40:0;7910:226:1;25777:406:0;25840:4;27896:21;;;:14;;;:21;;;;;;25856:321;;-1:-1:-1;25898:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;26080:18;;26056:21;;;:14;;;:21;;;;;;:42;;;;26112:11;;26351:1368;26417:4;26546:21;;;:14;;;:21;;;;;;26582:13;;26578:1135;;26949:18;26970:12;26981:1;26970:8;:12;:::i;:::-;27016:18;;26949:33;;-1:-1:-1;26996:17:0;;27016:22;;27037:1;;27016:22;:::i;:::-;26996:42;;27071:9;27057:10;:23;27053:378;;27100:17;27120:3;:11;;27132:9;27120:22;;;;;;;;:::i;:::-;;;;;;;;;27100:42;;27267:9;27241:3;:11;;27253:10;27241:23;;;;;;;;:::i;:::-;;;;;;;;;;;;:35;;;;27380:25;;;:14;;;:25;;;;;:36;;;27053:378;27509:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;27612:3;:14;;:21;27627:5;27612:21;;;;;;;;;;;27605:28;;;27655:4;27648:11;;;;;;;26578:1135;27697:5;27690:12;;;;;18112:151;18187:12;18218:38;18240:6;18248:4;18254:1;18187:12;18828;18842:23;18869:6;:11;;18888:5;18895:4;18869:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18827:73;;;;18917:55;18944:6;18952:7;18961:10;18917:26;:55::i;:::-;18910:62;18587:392;-1:-1:-1;;;;;;18587:392:0:o;20032:582::-;20176:12;20205:7;20200:408;;20228:19;20236:10;20228:7;:19::i;:::-;20200:408;;;20452:17;;:22;:49;;;;-1:-1:-1;20478:18:0;;;;:23;20452:49;20448:119;;;20528:24;;;;;8086:42:1;8074:55;;20528:24:0;;;8056:74:1;8029:18;;20528:24:0;7910:226:1;20448:119:0;-1:-1:-1;20587:10:0;20580:17;;21150:516;21281:17;;:21;21277:383;;21509:10;21503:17;21565:15;21552:10;21548:2;21544:19;21537:44;21277:383;21632:17;;;;;;;;;;;;;;14:332:1;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;180:9;167:23;230:66;223:5;219:78;212:5;209:89;199:117;;312:1;309;302:12;821:154;907:42;900:5;896:54;889:5;886:65;876:93;;965:1;962;955:12;980:134;1048:20;;1077:31;1048:20;1077:31;:::i;:::-;980:134;;;:::o;1119:388::-;1187:6;1195;1248:2;1236:9;1227:7;1223:23;1219:32;1216:52;;;1264:1;1261;1254:12;1216:52;1303:9;1290:23;1322:31;1347:5;1322:31;:::i;:::-;1372:5;-1:-1:-1;1429:2:1;1414:18;;1401:32;1442:33;1401:32;1442:33;:::i;:::-;1494:7;1484:17;;;1119:388;;;;;:::o;1694:180::-;1753:6;1806:2;1794:9;1785:7;1781:23;1777:32;1774:52;;;1822:1;1819;1812:12;1774:52;-1:-1:-1;1845:23:1;;1694:180;-1:-1:-1;1694:180:1:o;1879:315::-;1947:6;1955;2008:2;1996:9;1987:7;1983:23;1979:32;1976:52;;;2024:1;2021;2014:12;1976:52;2060:9;2047:23;2037:33;;2120:2;2109:9;2105:18;2092:32;2133:31;2158:5;2133:31;:::i;2199:184::-;2251:77;2248:1;2241:88;2348:4;2345:1;2338:15;2372:4;2369:1;2362:15;2388:255;2460:2;2454:9;2502:6;2490:19;;2539:18;2524:34;;2560:22;;;2521:62;2518:88;;;2586:18;;:::i;:::-;2622:2;2615:22;2388:255;:::o;2648:247::-;2715:2;2709:9;2757:3;2745:16;;2791:18;2776:34;;2812:22;;;2773:62;2770:88;;;2838:18;;:::i;2900:777::-;2942:5;2995:3;2988:4;2980:6;2976:17;2972:27;2962:55;;3013:1;3010;3003:12;2962:55;3049:6;3036:20;3075:18;3112:2;3108;3105:10;3102:36;;;3118:18;;:::i;:::-;3252:2;3246:9;3314:4;3306:13;;3157:66;3302:22;;;3326:2;3298:31;3294:40;3282:53;;;3350:18;;;3370:22;;;3347:46;3344:72;;;3396:18;;:::i;:::-;3436:10;3432:2;3425:22;3471:2;3463:6;3456:18;3517:3;3510:4;3505:2;3497:6;3493:15;3489:26;3486:35;3483:55;;;3534:1;3531;3524:12;3483:55;3598:2;3591:4;3583:6;3579:17;3572:4;3564:6;3560:17;3547:54;3645:1;3638:4;3633:2;3625:6;3621:15;3617:26;3610:37;3665:6;3656:15;;;;;;2900:777;;;;:::o;3682:455::-;3759:6;3767;3820:2;3808:9;3799:7;3795:23;3791:32;3788:52;;;3836:1;3833;3826:12;3788:52;3876:9;3863:23;3909:18;3901:6;3898:30;3895:50;;;3941:1;3938;3931:12;3895:50;3964:49;4005:7;3996:6;3985:9;3981:22;3964:49;:::i;:::-;3954:59;;;4063:2;4052:9;4048:18;4035:32;4076:31;4101:5;4076:31;:::i;4142:121::-;4227:10;4220:5;4216:22;4209:5;4206:33;4196:61;;4253:1;4250;4243:12;4268:132;4335:20;;4364:30;4335:20;4364:30;:::i;4405:118::-;4491:5;4484:13;4477:21;4470:5;4467:32;4457:60;;4513:1;4510;4503:12;4528:128;4593:20;;4622:28;4593:20;4622:28;:::i;4661:806::-;4720:5;4768:6;4756:9;4751:3;4747:19;4743:32;4740:52;;;4788:1;4785;4778:12;4740:52;4810:22;;:::i;:::-;4801:31;;4855:28;4873:9;4855:28;:::i;:::-;4848:5;4841:43;4916:38;4950:2;4939:9;4935:18;4916:38;:::i;:::-;4911:2;4904:5;4900:14;4893:62;4987:38;5021:2;5010:9;5006:18;4987:38;:::i;:::-;4982:2;4975:5;4971:14;4964:62;5058:38;5092:2;5081:9;5077:18;5058:38;:::i;:::-;5053:2;5046:5;5042:14;5035:62;5130:39;5164:3;5153:9;5149:19;5130:39;:::i;:::-;5124:3;5117:5;5113:15;5106:64;5231:3;5220:9;5216:19;5203:33;5197:3;5190:5;5186:15;5179:58;5298:3;5287:9;5283:19;5270:33;5264:3;5257:5;5253:15;5246:58;5337:36;5368:3;5357:9;5353:19;5337:36;:::i;:::-;5331:3;5324:5;5320:15;5313:61;5393:3;5456:2;5445:9;5441:18;5428:32;5423:2;5416:5;5412:14;5405:56;;4661:806;;;;:::o;5472:237::-;5560:6;5613:3;5601:9;5592:7;5588:23;5584:33;5581:53;;;5630:1;5627;5620:12;5581:53;5653:50;5695:7;5684:9;5653:50;:::i;5714:320::-;5782:6;5835:2;5823:9;5814:7;5810:23;5806:32;5803:52;;;5851:1;5848;5841:12;5803:52;5891:9;5878:23;5924:18;5916:6;5913:30;5910:50;;;5956:1;5953;5946:12;5910:50;5979:49;6020:7;6011:6;6000:9;5996:22;5979:49;:::i;:::-;5969:59;5714:320;-1:-1:-1;;;;5714:320:1:o;6039:273::-;6115:6;6168:2;6156:9;6147:7;6143:23;6139:32;6136:52;;;6184:1;6181;6174:12;6136:52;6223:9;6210:23;6262:1;6255:5;6252:12;6242:40;;6278:1;6275;6268:12;6317:250;6402:1;6412:113;6426:6;6423:1;6420:13;6412:113;;;6502:11;;;6496:18;6483:11;;;6476:39;6448:2;6441:10;6412:113;;;-1:-1:-1;;6559:1:1;6541:16;;6534:27;6317:250::o;6572:330::-;6614:3;6652:5;6646:12;6679:6;6674:3;6667:19;6695:76;6764:6;6757:4;6752:3;6748:14;6741:4;6734:5;6730:16;6695:76;:::i;:::-;6816:2;6804:15;6821:66;6800:88;6791:98;;;;6891:4;6787:109;;6572:330;-1:-1:-1;;6572:330:1:o;6907:220::-;7056:2;7045:9;7038:21;7019:4;7076:45;7117:2;7106:9;7102:18;7094:6;7076:45;:::i;7132:388::-;7209:6;7217;7270:2;7258:9;7249:7;7245:23;7241:32;7238:52;;;7286:1;7283;7276:12;7238:52;7326:9;7313:23;7359:18;7351:6;7348:30;7345:50;;;7391:1;7388;7381:12;7345:50;7414:49;7455:7;7446:6;7435:9;7431:22;7414:49;:::i;:::-;7404:59;7510:2;7495:18;;;;7482:32;;-1:-1:-1;;;;7132:388:1:o;7525:248::-;7593:6;7601;7654:2;7642:9;7633:7;7629:23;7625:32;7622:52;;;7670:1;7667;7660:12;7622:52;-1:-1:-1;;7693:23:1;;;7763:2;7748:18;;;7735:32;;-1:-1:-1;7525:248:1:o;8240:1373::-;8471:13;;8217:10;8206:22;8194:35;;8440:3;8425:19;;8543:4;8535:6;8531:17;8525:24;8558:53;8605:4;8594:9;8590:20;8576:12;8217:10;8206:22;8194:35;;8141:94;8558:53;;8660:4;8652:6;8648:17;8642:24;8675:56;8725:4;8714:9;8710:20;8694:14;7855:42;7844:54;7832:67;;7778:127;8675:56;;8780:4;8772:6;8768:17;8762:24;8795:56;8845:4;8834:9;8830:20;8814:14;7855:42;7844:54;7832:67;;7778:127;8795:56;;8900:4;8892:6;8888:17;8882:24;8915:56;8965:4;8954:9;8950:20;8934:14;7855:42;7844:54;7832:67;;7778:127;8915:56;;9020:4;9012:6;9008:17;9002:24;9035:56;9085:4;9074:9;9070:20;9054:14;7855:42;7844:54;7832:67;;7778:127;9035:56;;9147:4;9139:6;9135:17;9129:24;9122:4;9111:9;9107:20;9100:54;9210:4;9202:6;9198:17;9192:24;9185:4;9174:9;9170:20;9163:54;9236:6;9296:2;9288:6;9284:15;9278:22;9273:2;9262:9;9258:18;9251:50;;9320:6;9375:2;9367:6;9363:15;9357:22;9388:51;9435:2;9424:9;9420:18;9404:14;421:13;414:21;402:34;;351:91;9388:51;-1:-1:-1;;9458:6:1;9506:15;;;9500:22;9480:18;;;9473:50;9542:6;9590:15;;;9584:22;9564:18;;;;9557:50;;;;8240:1373;:::o;9618:440::-;9724:6;9732;9740;9793:3;9781:9;9772:7;9768:23;9764:33;9761:53;;;9810:1;9807;9800:12;9761:53;9846:9;9833:23;9823:33;;9906:2;9895:9;9891:18;9878:32;9919:31;9944:5;9919:31;:::i;:::-;9969:5;-1:-1:-1;9993:59:1;10044:7;10039:2;10024:18;;9993:59;:::i;:::-;9983:69;;9618:440;;;;;:::o;10063:523::-;10149:6;10157;10165;10218:2;10206:9;10197:7;10193:23;10189:32;10186:52;;;10234:1;10231;10224:12;10186:52;10270:9;10257:23;10247:33;;10330:2;10319:9;10315:18;10302:32;10343:31;10368:5;10343:31;:::i;:::-;10393:5;-1:-1:-1;10449:2:1;10434:18;;10421:32;10476:18;10465:30;;10462:50;;;10508:1;10505;10498:12;10462:50;10531:49;10572:7;10563:6;10552:9;10548:22;10531:49;:::i;:::-;10521:59;;;10063:523;;;;;:::o;10776:1087::-;10906:6;10914;10922;10930;10938;10946;10954;10962;10970;11023:3;11011:9;11002:7;10998:23;10994:33;10991:53;;;11040:1;11037;11030:12;10991:53;11076:9;11063:23;11053:33;;11136:2;11125:9;11121:18;11108:32;11149:31;11174:5;11149:31;:::i;:::-;11199:5;-1:-1:-1;11256:2:1;11241:18;;11228:32;11269:33;11228:32;11269:33;:::i;:::-;11321:7;-1:-1:-1;11380:2:1;11365:18;;11352:32;11393;11352;11393;:::i;:::-;11444:7;-1:-1:-1;11503:3:1;11488:19;;11475:33;11517;11475;11517;:::i;:::-;11569:7;-1:-1:-1;11628:3:1;11613:19;;11600:33;11642;11600;11642;:::i;:::-;11694:7;11684:17;;;11748:3;11737:9;11733:19;11720:33;11710:43;;11800:3;11789:9;11785:19;11772:33;11762:43;;11852:3;11841:9;11837:19;11824:33;11814:43;;10776:1087;;;;;;;;;;;:::o;11868:247::-;11927:6;11980:2;11968:9;11959:7;11955:23;11951:32;11948:52;;;11996:1;11993;11986:12;11948:52;12035:9;12022:23;12054:31;12079:5;12054:31;:::i;12867:184::-;12919:77;12916:1;12909:88;13016:4;13013:1;13006:15;13040:4;13037:1;13030:15;13056:136;13134:13;;13156:30;13134:13;13156:30;:::i;13197:138::-;13276:13;;13298:31;13276:13;13298:31;:::i;13340:132::-;13416:13;;13438:28;13416:13;13438:28;:::i;13477:1183::-;13580:6;13633:3;13621:9;13612:7;13608:23;13604:33;13601:53;;;13650:1;13647;13640:12;13601:53;13676:17;;:::i;:::-;13716:39;13745:9;13716:39;:::i;:::-;13709:5;13702:54;13788:48;13832:2;13821:9;13817:18;13788:48;:::i;:::-;13783:2;13776:5;13772:14;13765:72;13869:49;13914:2;13903:9;13899:18;13869:49;:::i;:::-;13864:2;13857:5;13853:14;13846:73;13951:49;13996:2;13985:9;13981:18;13951:49;:::i;:::-;13946:2;13939:5;13935:14;13928:73;14034:50;14079:3;14068:9;14064:19;14034:50;:::i;:::-;14028:3;14021:5;14017:15;14010:75;14118:50;14163:3;14152:9;14148:19;14118:50;:::i;:::-;14112:3;14105:5;14101:15;14094:75;14223:3;14212:9;14208:19;14202:26;14196:3;14189:5;14185:15;14178:51;14283:3;14272:9;14268:19;14262:26;14256:3;14249:5;14245:15;14238:51;14308:3;14364:2;14353:9;14349:18;14343:25;14338:2;14331:5;14327:14;14320:49;;14388:3;14423:46;14465:2;14454:9;14450:18;14423:46;:::i;:::-;14407:14;;;14400:70;14489:3;14530:18;;;14524:25;14508:14;;;14501:49;14569:3;14610:18;;;14604:25;14588:14;;;14581:49;;;;-1:-1:-1;14411:5:1;13477:1183;-1:-1:-1;13477:1183:1:o;14665:184::-;14717:77;14714:1;14707:88;14814:4;14811:1;14804:15;14838:4;14835:1;14828:15;14854:168;14927:9;;;14958;;14975:15;;;14969:22;;14955:37;14945:71;;14996:18;;:::i;15027:274::-;15067:1;15093;15083:189;;15128:77;15125:1;15118:88;15229:4;15226:1;15219:15;15257:4;15254:1;15247:15;15083:189;-1:-1:-1;15286:9:1;;15027:274::o;15306:128::-;15373:9;;;15394:11;;;15391:37;;;15408:18;;:::i;15439:195::-;15478:3;15509:66;15502:5;15499:77;15496:103;;15579:18;;:::i;:::-;-1:-1:-1;15626:1:1;15615:13;;15439:195::o;15639:753::-;15946:3;15935:9;15928:22;15909:4;15967:46;16008:3;15997:9;15993:19;15985:6;15967:46;:::i;:::-;16061:10;16049:23;;;;16044:2;16029:18;;16022:51;-1:-1:-1;16092:42:1;16170:15;;;16165:2;16150:18;;16143:43;16222:15;;;;16217:2;16202:18;;16195:43;16269:3;16254:19;;16247:35;;;;16313:3;16298:19;;16291:35;16370:14;;16363:22;16357:3;16342:19;;;16335:51;15959:54;15639:753;-1:-1:-1;15639:753:1:o;18791:184::-;18843:77;18840:1;18833:88;18940:4;18937:1;18930:15;18964:4;18961:1;18954:15;18980:245;19047:6;19100:2;19088:9;19079:7;19075:23;19071:32;19068:52;;;19116:1;19113;19106:12;19068:52;19148:9;19142:16;19167:28;19189:5;19167:28;:::i;19230:184::-;19282:77;19279:1;19272:88;19379:4;19376:1;19369:15;19403:4;19400:1;19393:15;19419:287;19548:3;19586:6;19580:13;19602:66;19661:6;19656:3;19649:4;19641:6;19637:17;19602:66;:::i;:::-;19684:16;;;;;19419:287;-1:-1:-1;;19419:287:1:o","abiDefinition":[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositRefunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"}],"name":"BridgeProofDisputed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":false,"internalType":"bytes32","name":"transactionHash","type":"bytes32"}],"name":"BridgeProofProvided","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint32","name":"originChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"chainGasAmount","type":"uint256"}],"name":"BridgeRelayed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes","name":"request","type":"bytes"},{"indexed":false,"internalType":"uint32","name":"destChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"sendChainGas","type":"bool"}],"name":"BridgeRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldChainGasAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"ChainGasAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFeeRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"FeeRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesSwept","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_RATE_MAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GOVERNOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GUARD_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFUNDER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAYER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstChainId","type":"uint32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IFastBridge.BridgeParams","name":"params","type":"tuple"}],"name":"bridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionid","type":"bytes32"},{"internalType":"address","name":"relayer","type":"address"}],"name":"canClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainGasAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"address","name":"to","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deployBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"dispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"getBridgeTransaction","outputs":[{"components":[{"internalType":"uint32","name":"originChainId","type":"uint32"},{"internalType":"uint32","name":"destChainId","type":"uint32"},{"internalType":"address","name":"originSender","type":"address"},{"internalType":"address","name":"destRecipient","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256","name":"originFeeAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct IFastBridge.BridgeTransaction","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"enum FastBridge.BridgeStatus","name":"keyValue","type":"uint8"}],"name":"getEnumKeyByValue","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"address","name":"relayer","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint32","name":"originChainId","type":"uint32"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256","name":"chainGasAmount","type":"uint256"}],"name":"mockBridgeRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"},{"components":[{"internalType":"uint32","name":"dstChainId","type":"uint32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IFastBridge.BridgeParams","name":"params","type":"tuple"}],"name":"mockBridgeRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"bytes","name":"request","type":"bytes"}],"name":"mockBridgeRequestRaw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"protocolFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"bytes32","name":"destTxHash","type":"bytes32"}],"name":"prove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"relay","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"setChainGasAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"setProtocolFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"sweepProtocolFees","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"notice":"Initiates bridge on origin chain to be relayed by off-chain relayer"},"chainGasAmount()":{"notice":"Chain gas amount to forward as rebate if requested"},"claim(bytes,address)":{"notice":"Completes bridge transaction on origin chain by claiming originally deposited capital"},"dispute(bytes32)":{"notice":"Disputes an outstanding proof in case relayer provided dest chain tx is invalid"},"getBridgeTransaction(bytes)":{"notice":"Decodes bridge request into a bridge transaction"},"protocolFeeRate()":{"notice":"Protocol fee rate taken on origin amount deposited in origin chain"},"protocolFees(address)":{"notice":"Protocol fee amounts accumulated"},"prove(bytes,bytes32)":{"notice":"Provides proof on origin side that relayer provided funds on destination side of bridge transaction"},"refund(bytes)":{"notice":"Refunds an outstanding bridge transaction in case optimistic bridging failed"},"relay(bytes)":{"notice":"Relays destination side of bridge transaction by off-chain relayer"}},"version":1},"developerDoc":{"errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}],"AddressEmptyCode(address)":[{"details":"There's no code at `target` (it is not a contract)."}],"AddressInsufficientBalance(address)":[{"details":"The ETH balance of the account is not enough to perform the operation."}],"FailedInnerCall()":[{"details":"A call to an address target failed. The target may have reverted."}],"SafeERC20FailedOperation(address)":[{"details":"An operation with an ERC-20 token failed."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"params":{"params":"The parameters required to bridge"}},"claim(bytes,address)":{"params":{"request":"The encoded bridge transaction to claim on origin chain","to":"The recipient address of the funds"}},"dispute(bytes32)":{"params":{"transactionId":"The transaction id associated with the encoded bridge transaction to dispute"}},"getBridgeTransaction(bytes)":{"params":{"request":"The bridge request to decode"}},"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"getRoleMember(bytes32,uint256)":{"details":"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information."},"getRoleMemberCount(bytes32)":{"details":"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"prove(bytes,bytes32)":{"params":{"destTxHash":"The destination tx hash proving bridge transaction was relayed","request":"The encoded bridge transaction to prove on origin chain"}},"refund(bytes)":{"params":{"request":"The encoded bridge transaction to refund"}},"relay(bytes)":{"params":{"request":"The encoded bridge transaction to relay on destination chain"}},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"supportsInterface(bytes4)":{"details":"See {IERC165-supportsInterface}."}},"stateVariables":{"nonce":{"details":"to prevent replays"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositRefunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"BridgeProofDisputed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"transactionHash\",\"type\":\"bytes32\"}],\"name\":\"BridgeProofProvided\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"BridgeRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"}],\"name\":\"BridgeRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_BPS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FEE_RATE_MAX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOVERNOR_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARD_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REFUNDER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAYER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"bridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionid\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"canClaim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainGasAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"dispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"getBridgeTransaction\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originSender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destRecipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originFeeAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeTransaction\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enum FastBridge.BridgeStatus\",\"name\":\"keyValue\",\"type\":\"uint8\"}],\"name\":\"getEnumKeyByValue\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"mockBridgeRelayer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"mockBridgeRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"mockBridgeRequestRaw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFeeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"destTxHash\",\"type\":\"bytes32\"}],\"name\":\"prove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"refund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}],\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"AddressInsufficientBalance(address)\":[{\"details\":\"The ETH balance of the account is not enough to perform the operation.\"}],\"FailedInnerCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"params\":{\"params\":\"The parameters required to bridge\"}},\"claim(bytes,address)\":{\"params\":{\"request\":\"The encoded bridge transaction to claim on origin chain\",\"to\":\"The recipient address of the funds\"}},\"dispute(bytes32)\":{\"params\":{\"transactionId\":\"The transaction id associated with the encoded bridge transaction to dispute\"}},\"getBridgeTransaction(bytes)\":{\"params\":{\"request\":\"The bridge request to decode\"}},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"getRoleMember(bytes32,uint256)\":{\"details\":\"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.\"},\"getRoleMemberCount(bytes32)\":{\"details\":\"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"prove(bytes,bytes32)\":{\"params\":{\"destTxHash\":\"The destination tx hash proving bridge transaction was relayed\",\"request\":\"The encoded bridge transaction to prove on origin chain\"}},\"refund(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to refund\"}},\"relay(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to relay on destination chain\"}},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"stateVariables\":{\"nonce\":{\"details\":\"to prevent replays\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"notice\":\"Initiates bridge on origin chain to be relayed by off-chain relayer\"},\"chainGasAmount()\":{\"notice\":\"Chain gas amount to forward as rebate if requested\"},\"claim(bytes,address)\":{\"notice\":\"Completes bridge transaction on origin chain by claiming originally deposited capital\"},\"dispute(bytes32)\":{\"notice\":\"Disputes an outstanding proof in case relayer provided dest chain tx is invalid\"},\"getBridgeTransaction(bytes)\":{\"notice\":\"Decodes bridge request into a bridge transaction\"},\"protocolFeeRate()\":{\"notice\":\"Protocol fee rate taken on origin amount deposited in origin chain\"},\"protocolFees(address)\":{\"notice\":\"Protocol fee amounts accumulated\"},\"prove(bytes,bytes32)\":{\"notice\":\"Provides proof on origin side that relayer provided funds on destination side of bridge transaction\"},\"refund(bytes)\":{\"notice\":\"Refunds an outstanding bridge transaction in case optimistic bridging failed\"},\"relay(bytes)\":{\"notice\":\"Relays destination side of bridge transaction by off-chain relayer\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"FastBridgeMock\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0x4fff59c4cd271340f4a824126cbe4ebe7c8dc20639e268edf42ff873af31f862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4d33ef4f98d2abd98b4bbcb403b27495c37843b37000bea9f48e533078144d84\",\"dweb:/ipfs/QmTMkQhtNJPVgpxiLnEG45Ww7xfXHMEoVQ5JdbEbaFXwwS\"]}},\"version\":1}"},"hashes":{"DEFAULT_ADMIN_ROLE()":"a217fddf","FEE_BPS()":"bf333f2c","FEE_RATE_MAX()":"0f5f6ed7","GOVERNOR_ROLE()":"ccc57490","GUARD_ROLE()":"03ed0ee5","REFUNDER_ROLE()":"5960ccf2","RELAYER_ROLE()":"926d7d7f","bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":"45851694","canClaim(bytes32,address)":"aa9641ab","chainGasAmount()":"e00a83e0","claim(bytes,address)":"41fcb612","deployBlock()":"a3ec191a","dispute(bytes32)":"add98c70","getBridgeTransaction(bytes)":"ac11fb1a","getEnumKeyByValue(uint8)":"85ad903d","getRoleAdmin(bytes32)":"248a9ca3","getRoleMember(bytes32,uint256)":"9010d07c","getRoleMemberCount(bytes32)":"ca15c873","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","mockBridgeRelayer(bytes32,address,address,uint32,address,address,uint256,uint256,uint256)":"c72870cc","mockBridgeRequest(bytes32,address,(uint32,address,address,address,address,uint256,uint256,bool,uint256))":"acaebbf1","mockBridgeRequestRaw(bytes32,address,bytes)":"aedf009d","nonce()":"affed0e0","protocolFeeRate()":"58f85880","protocolFees(address)":"dcf844a7","prove(bytes,bytes32)":"886d36ff","refund(bytes)":"5eb7d946","relay(bytes)":"8f0d6f17","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","setChainGasAmount(uint256)":"b250fe6b","setProtocolFeeRate(uint256)":"b13aa2d6","supportsInterface(bytes4)":"01ffc9a7","sweepProtocolFees(address,address)":"06f333f2"}},"solidity/FastBridgeMock.sol:IAccessControl":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n )\n external\n {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"External interface of AccessControl declared to support ERC-165 detection.","errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {AccessControl-_setRoleAdmin}."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"External interface of AccessControl declared to support ERC-165 detection.\",\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {AccessControl-_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"IAccessControl\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0x4fff59c4cd271340f4a824126cbe4ebe7c8dc20639e268edf42ff873af31f862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4d33ef4f98d2abd98b4bbcb403b27495c37843b37000bea9f48e533078144d84\",\"dweb:/ipfs/QmTMkQhtNJPVgpxiLnEG45Ww7xfXHMEoVQ5JdbEbaFXwwS\"]}},\"version\":1}"},"hashes":{"getRoleAdmin(bytes32)":"248a9ca3","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f"}},"solidity/FastBridgeMock.sol:IAccessControlEnumerable":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n )\n external\n {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"External interface of AccessControlEnumerable declared to support ERC-165 detection.","errors":{"AccessControlBadConfirmation()":[{"details":"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}."}],"AccessControlUnauthorizedAccount(address,bytes32)":[{"details":"The `account` is missing a role."}]},"events":{"RoleAdminChanged(bytes32,bytes32,bytes32)":{"details":"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this."},"RoleGranted(bytes32,address,address)":{"details":"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."},"RoleRevoked(bytes32,address,address)":{"details":"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)"}},"kind":"dev","methods":{"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {AccessControl-_setRoleAdmin}."},"getRoleMember(bytes32,uint256)":{"details":"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information."},"getRoleMemberCount(bytes32)":{"details":"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role."},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role."},"hasRole(bytes32,address)":{"details":"Returns `true` if `account` has been granted `role`."},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"External interface of AccessControlEnumerable declared to support ERC-165 detection.\",\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}]},\"events\":{\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"}},\"kind\":\"dev\",\"methods\":{\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {AccessControl-_setRoleAdmin}.\"},\"getRoleMember(bytes32,uint256)\":{\"details\":\"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.\"},\"getRoleMemberCount(bytes32)\":{\"details\":\"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"IAccessControlEnumerable\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0x4fff59c4cd271340f4a824126cbe4ebe7c8dc20639e268edf42ff873af31f862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4d33ef4f98d2abd98b4bbcb403b27495c37843b37000bea9f48e533078144d84\",\"dweb:/ipfs/QmTMkQhtNJPVgpxiLnEG45Ww7xfXHMEoVQ5JdbEbaFXwwS\"]}},\"version\":1}"},"hashes":{"getRoleAdmin(bytes32)":"248a9ca3","getRoleMember(bytes32,uint256)":"9010d07c","getRoleMemberCount(bytes32)":"ca15c873","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f"}},"solidity/FastBridgeMock.sol:IAdmin":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n )\n external\n {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldChainGasAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"ChainGasAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFeeRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"FeeRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesSwept","type":"event"},{"inputs":[{"internalType":"uint256","name":"newChainGasAmount","type":"uint256"}],"name":"setChainGasAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"setProtocolFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"sweepProtocolFees","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldChainGasAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"ChainGasAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFeeRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"FeeRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesSwept\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newChainGasAmount\",\"type\":\"uint256\"}],\"name\":\"setChainGasAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFeeRate\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"IAdmin\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0x4fff59c4cd271340f4a824126cbe4ebe7c8dc20639e268edf42ff873af31f862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4d33ef4f98d2abd98b4bbcb403b27495c37843b37000bea9f48e533078144d84\",\"dweb:/ipfs/QmTMkQhtNJPVgpxiLnEG45Ww7xfXHMEoVQ5JdbEbaFXwwS\"]}},\"version\":1}"},"hashes":{"setChainGasAmount(uint256)":"b250fe6b","setProtocolFeeRate(uint256)":"b13aa2d6","sweepProtocolFees(address,address)":"06f333f2"}},"solidity/FastBridgeMock.sol:IERC165":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n )\n external\n {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Interface of the ERC-165 standard, as defined in the https://eips.ethereum.org/EIPS/eip-165[ERC]. Implementers can declare support of contract interfaces, which can then be queried by others ({ERC165Checker}). For an implementation, see {ERC165}.","kind":"dev","methods":{"supportsInterface(bytes4)":{"details":"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Interface of the ERC-165 standard, as defined in the https://eips.ethereum.org/EIPS/eip-165[ERC]. Implementers can declare support of contract interfaces, which can then be queried by others ({ERC165Checker}). For an implementation, see {ERC165}.\",\"kind\":\"dev\",\"methods\":{\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"IERC165\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0x4fff59c4cd271340f4a824126cbe4ebe7c8dc20639e268edf42ff873af31f862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4d33ef4f98d2abd98b4bbcb403b27495c37843b37000bea9f48e533078144d84\",\"dweb:/ipfs/QmTMkQhtNJPVgpxiLnEG45Ww7xfXHMEoVQ5JdbEbaFXwwS\"]}},\"version\":1}"},"hashes":{"supportsInterface(bytes4)":"01ffc9a7"}},"solidity/FastBridgeMock.sol:IERC20":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n )\n external\n {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Interface of the ERC-20 standard as defined in the ERC.","events":{"Approval(address,address,uint256)":{"details":"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance."},"Transfer(address,address,uint256)":{"details":"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero."}},"kind":"dev","methods":{"allowance(address,address)":{"details":"Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through {transferFrom}. This is zero by default. This value changes when {approve} or {transferFrom} are called."},"approve(address,uint256)":{"details":"Sets a `value` amount of tokens as the allowance of `spender` over the caller's tokens. Returns a boolean value indicating whether the operation succeeded. IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 Emits an {Approval} event."},"balanceOf(address)":{"details":"Returns the value of tokens owned by `account`."},"totalSupply()":{"details":"Returns the value of tokens in existence."},"transfer(address,uint256)":{"details":"Moves a `value` amount of tokens from the caller's account to `to`. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event."},"transferFrom(address,address,uint256)":{"details":"Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism. `value` is then deducted from the caller's allowance. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Interface of the ERC-20 standard as defined in the ERC.\",\"events\":{\"Approval(address,address,uint256)\":{\"details\":\"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance.\"},\"Transfer(address,address,uint256)\":{\"details\":\"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero.\"}},\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner` through {transferFrom}. This is zero by default. This value changes when {approve} or {transferFrom} are called.\"},\"approve(address,uint256)\":{\"details\":\"Sets a `value` amount of tokens as the allowance of `spender` over the caller's tokens. Returns a boolean value indicating whether the operation succeeded. IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 Emits an {Approval} event.\"},\"balanceOf(address)\":{\"details\":\"Returns the value of tokens owned by `account`.\"},\"totalSupply()\":{\"details\":\"Returns the value of tokens in existence.\"},\"transfer(address,uint256)\":{\"details\":\"Moves a `value` amount of tokens from the caller's account to `to`. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism. `value` is then deducted from the caller's allowance. Returns a boolean value indicating whether the operation succeeded. Emits a {Transfer} event.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"IERC20\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0x4fff59c4cd271340f4a824126cbe4ebe7c8dc20639e268edf42ff873af31f862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4d33ef4f98d2abd98b4bbcb403b27495c37843b37000bea9f48e533078144d84\",\"dweb:/ipfs/QmTMkQhtNJPVgpxiLnEG45Ww7xfXHMEoVQ5JdbEbaFXwwS\"]}},\"version\":1}"},"hashes":{"allowance(address,address)":"dd62ed3e","approve(address,uint256)":"095ea7b3","balanceOf(address)":"70a08231","totalSupply()":"18160ddd","transfer(address,uint256)":"a9059cbb","transferFrom(address,address,uint256)":"23b872dd"}},"solidity/FastBridgeMock.sol:IERC20Permit":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n )\n external\n {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in https://eips.ethereum.org/EIPS/eip-2612[ERC-2612]. Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't need to send a transaction, and thus is not required to hold Ether at all. ==== Security Considerations There are two important considerations concerning the use of `permit`. The first is that a valid permit signature expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be considered as an intention to spend the allowance in any specific way. The second is that because permits have built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be generally recommended is: ```solidity function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} doThing(..., value); } function doThing(..., uint256 value) public { token.safeTransferFrom(msg.sender, address(this), value); ... } ``` Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also {SafeERC20-safeTransferFrom}). Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so contracts should have entry points that don't rely on permit.","kind":"dev","methods":{"DOMAIN_SEPARATOR()":{"details":"Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}."},"nonces(address)":{"details":"Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times."},"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)":{"details":"Sets `value` as the allowance of `spender` over ``owner``'s tokens, given ``owner``'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. CAUTION: See Security Considerations above."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in https://eips.ethereum.org/EIPS/eip-2612[ERC-2612]. Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't need to send a transaction, and thus is not required to hold Ether at all. ==== Security Considerations There are two important considerations concerning the use of `permit`. The first is that a valid permit signature expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be considered as an intention to spend the allowance in any specific way. The second is that because permits have built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be generally recommended is: ```solidity function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} doThing(..., value); } function doThing(..., uint256 value) public { token.safeTransferFrom(msg.sender, address(this), value); ... } ``` Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also {SafeERC20-safeTransferFrom}). Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so contracts should have entry points that don't rely on permit.\",\"kind\":\"dev\",\"methods\":{\"DOMAIN_SEPARATOR()\":{\"details\":\"Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\"},\"nonces(address)\":{\"details\":\"Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times.\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Sets `value` as the allowance of `spender` over ``owner``'s tokens, given ``owner``'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. CAUTION: See Security Considerations above.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"IERC20Permit\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0x4fff59c4cd271340f4a824126cbe4ebe7c8dc20639e268edf42ff873af31f862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4d33ef4f98d2abd98b4bbcb403b27495c37843b37000bea9f48e533078144d84\",\"dweb:/ipfs/QmTMkQhtNJPVgpxiLnEG45Ww7xfXHMEoVQ5JdbEbaFXwwS\"]}},\"version\":1}"},"hashes":{"DOMAIN_SEPARATOR()":"3644e515","nonces(address)":"7ecebe00","permit(address,address,uint256,uint256,uint8,bytes32,bytes32)":"d505accf"}},"solidity/FastBridgeMock.sol:IFastBridge":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n )\n external\n {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeDepositRefunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"}],"name":"BridgeProofDisputed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":false,"internalType":"bytes32","name":"transactionHash","type":"bytes32"}],"name":"BridgeProofProvided","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint32","name":"originChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"chainGasAmount","type":"uint256"}],"name":"BridgeRelayed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes","name":"request","type":"bytes"},{"indexed":false,"internalType":"uint32","name":"destChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"originToken","type":"address"},{"indexed":false,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"originAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"sendChainGas","type":"bool"}],"name":"BridgeRequested","type":"event"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstChainId","type":"uint32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IFastBridge.BridgeParams","name":"params","type":"tuple"}],"name":"bridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"address","name":"relayer","type":"address"}],"name":"canClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"address","name":"to","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"name":"dispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"getBridgeTransaction","outputs":[{"components":[{"internalType":"uint32","name":"originChainId","type":"uint32"},{"internalType":"uint32","name":"destChainId","type":"uint32"},{"internalType":"address","name":"originSender","type":"address"},{"internalType":"address","name":"destRecipient","type":"address"},{"internalType":"address","name":"originToken","type":"address"},{"internalType":"address","name":"destToken","type":"address"},{"internalType":"uint256","name":"originAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256","name":"originFeeAmount","type":"uint256"},{"internalType":"bool","name":"sendChainGas","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct IFastBridge.BridgeTransaction","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"bytes32","name":"destTxHash","type":"bytes32"}],"name":"prove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"request","type":"bytes"}],"name":"relay","outputs":[],"stateMutability":"payable","type":"function"}],"userDoc":{"kind":"user","methods":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"notice":"Initiates bridge on origin chain to be relayed by off-chain relayer"},"canClaim(bytes32,address)":{"notice":"Checks if the dispute period has passed so bridge deposit can be claimed"},"claim(bytes,address)":{"notice":"Completes bridge transaction on origin chain by claiming originally deposited capital"},"dispute(bytes32)":{"notice":"Disputes an outstanding proof in case relayer provided dest chain tx is invalid"},"getBridgeTransaction(bytes)":{"notice":"Decodes bridge request into a bridge transaction"},"prove(bytes,bytes32)":{"notice":"Provides proof on origin side that relayer provided funds on destination side of bridge transaction"},"refund(bytes)":{"notice":"Refunds an outstanding bridge transaction in case optimistic bridging failed"},"relay(bytes)":{"notice":"Relays destination side of bridge transaction by off-chain relayer"}},"version":1},"developerDoc":{"kind":"dev","methods":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":{"params":{"params":"The parameters required to bridge"}},"canClaim(bytes32,address)":{"params":{"relayer":"The address of the relayer attempting to claim","transactionId":"The transaction id associated with the encoded bridge transaction to check"}},"claim(bytes,address)":{"params":{"request":"The encoded bridge transaction to claim on origin chain","to":"The recipient address of the funds"}},"dispute(bytes32)":{"params":{"transactionId":"The transaction id associated with the encoded bridge transaction to dispute"}},"getBridgeTransaction(bytes)":{"params":{"request":"The bridge request to decode"}},"prove(bytes,bytes32)":{"params":{"destTxHash":"The destination tx hash proving bridge transaction was relayed","request":"The encoded bridge transaction to prove on origin chain"}},"refund(bytes)":{"params":{"request":"The encoded bridge transaction to refund"}},"relay(bytes)":{"params":{"request":"The encoded bridge transaction to relay on destination chain"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"BridgeDepositRefunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"BridgeProofDisputed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"transactionHash\",\"type\":\"bytes32\"}],\"name\":\"BridgeProofProvided\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainGasAmount\",\"type\":\"uint256\"}],\"name\":\"BridgeRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"}],\"name\":\"BridgeRequested\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"bridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"}],\"name\":\"canClaim\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"}],\"name\":\"dispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"getBridgeTransaction\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"originChainId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destChainId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originSender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destRecipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"originAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originFeeAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendChainGas\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"internalType\":\"struct IFastBridge.BridgeTransaction\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"destTxHash\",\"type\":\"bytes32\"}],\"name\":\"prove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"refund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"request\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"params\":{\"params\":\"The parameters required to bridge\"}},\"canClaim(bytes32,address)\":{\"params\":{\"relayer\":\"The address of the relayer attempting to claim\",\"transactionId\":\"The transaction id associated with the encoded bridge transaction to check\"}},\"claim(bytes,address)\":{\"params\":{\"request\":\"The encoded bridge transaction to claim on origin chain\",\"to\":\"The recipient address of the funds\"}},\"dispute(bytes32)\":{\"params\":{\"transactionId\":\"The transaction id associated with the encoded bridge transaction to dispute\"}},\"getBridgeTransaction(bytes)\":{\"params\":{\"request\":\"The bridge request to decode\"}},\"prove(bytes,bytes32)\":{\"params\":{\"destTxHash\":\"The destination tx hash proving bridge transaction was relayed\",\"request\":\"The encoded bridge transaction to prove on origin chain\"}},\"refund(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to refund\"}},\"relay(bytes)\":{\"params\":{\"request\":\"The encoded bridge transaction to relay on destination chain\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))\":{\"notice\":\"Initiates bridge on origin chain to be relayed by off-chain relayer\"},\"canClaim(bytes32,address)\":{\"notice\":\"Checks if the dispute period has passed so bridge deposit can be claimed\"},\"claim(bytes,address)\":{\"notice\":\"Completes bridge transaction on origin chain by claiming originally deposited capital\"},\"dispute(bytes32)\":{\"notice\":\"Disputes an outstanding proof in case relayer provided dest chain tx is invalid\"},\"getBridgeTransaction(bytes)\":{\"notice\":\"Decodes bridge request into a bridge transaction\"},\"prove(bytes,bytes32)\":{\"notice\":\"Provides proof on origin side that relayer provided funds on destination side of bridge transaction\"},\"refund(bytes)\":{\"notice\":\"Refunds an outstanding bridge transaction in case optimistic bridging failed\"},\"relay(bytes)\":{\"notice\":\"Relays destination side of bridge transaction by off-chain relayer\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"IFastBridge\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0x4fff59c4cd271340f4a824126cbe4ebe7c8dc20639e268edf42ff873af31f862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4d33ef4f98d2abd98b4bbcb403b27495c37843b37000bea9f48e533078144d84\",\"dweb:/ipfs/QmTMkQhtNJPVgpxiLnEG45Ww7xfXHMEoVQ5JdbEbaFXwwS\"]}},\"version\":1}"},"hashes":{"bridge((uint32,address,address,address,address,uint256,uint256,bool,uint256))":"45851694","canClaim(bytes32,address)":"aa9641ab","claim(bytes,address)":"41fcb612","dispute(bytes32)":"add98c70","getBridgeTransaction(bytes)":"ac11fb1a","prove(bytes,bytes32)":"886d36ff","refund(bytes)":"5eb7d946","relay(bytes)":"8f0d6f17"}},"solidity/FastBridgeMock.sol:SafeERC20":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c51b222f1984df769e9e9836d8b17da22ec98bfb801c9728e848da279f2ef33e64736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c51b222f1984df769e9e9836d8b17da22ec98bfb801c9728e848da279f2ef33e64736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n )\n external\n {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"39265:5019:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;39265:5019:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"39265:5019:0:-:0;;;;;;;;","abiDefinition":[{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"currentAllowance","type":"uint256"},{"internalType":"uint256","name":"requestedDecrease","type":"uint256"}],"name":"SafeERC20FailedDecreaseAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Wrappers around ERC-20 operations that throw on failure (when the token contract returns false). Tokens that return no value (and instead revert or throw on failure) are also supported, non-reverting calls are assumed to be successful. To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, which allows you to call the safe operations as `token.safeTransfer(...)`, etc.","errors":{"SafeERC20FailedDecreaseAllowance(address,uint256,uint256)":[{"details":"Indicates a failed `decreaseAllowance` request."}],"SafeERC20FailedOperation(address)":[{"details":"An operation with an ERC-20 token failed."}]},"kind":"dev","methods":{},"title":"SafeERC20","version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"currentAllowance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestedDecrease\",\"type\":\"uint256\"}],\"name\":\"SafeERC20FailedDecreaseAllowance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"}],\"devdoc\":{\"details\":\"Wrappers around ERC-20 operations that throw on failure (when the token contract returns false). Tokens that return no value (and instead revert or throw on failure) are also supported, non-reverting calls are assumed to be successful. To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\",\"errors\":{\"SafeERC20FailedDecreaseAllowance(address,uint256,uint256)\":[{\"details\":\"Indicates a failed `decreaseAllowance` request.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}]},\"kind\":\"dev\",\"methods\":{},\"title\":\"SafeERC20\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"SafeERC20\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0x4fff59c4cd271340f4a824126cbe4ebe7c8dc20639e268edf42ff873af31f862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4d33ef4f98d2abd98b4bbcb403b27495c37843b37000bea9f48e533078144d84\",\"dweb:/ipfs/QmTMkQhtNJPVgpxiLnEG45Ww7xfXHMEoVQ5JdbEbaFXwwS\"]}},\"version\":1}"},"hashes":{}},"solidity/FastBridgeMock.sol:UniversalTokenLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220091110fff57e33a0f49e1afe323fd28b79984a963c9cb8afaca914399291e9a964736f6c63430008140033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220091110fff57e33a0f49e1afe323fd28b79984a963c9cb8afaca914399291e9a964736f6c63430008140033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.20 ^0.8.0 ^0.8.20;\n\n// contracts/interfaces/IAdmin.sol\n\ninterface IAdmin {\n // ============ Events ============\n\n event FeeRateUpdated(uint256 oldFeeRate, uint256 newFeeRate);\n event FeesSwept(address token, address recipient, uint256 amount);\n\n event ChainGasAmountUpdated(uint256 oldChainGasAmount, uint256 newChainGasAmount);\n\n // ============ Methods ============\n\n function setProtocolFeeRate(uint256 newFeeRate) external;\n\n function sweepProtocolFees(address token, address recipient) external;\n\n function setChainGasAmount(uint256 newChainGasAmount) external;\n}\n\n// contracts/interfaces/IFastBridge.sol\n\ninterface IFastBridge {\n struct BridgeTransaction {\n uint32 originChainId;\n uint32 destChainId;\n address originSender; // user (origin)\n address destRecipient; // user (dest)\n address originToken;\n address destToken;\n uint256 originAmount; // amount in on origin bridge less originFeeAmount\n uint256 destAmount;\n uint256 originFeeAmount;\n bool sendChainGas;\n uint256 deadline; // user specified deadline for destination relay\n uint256 nonce;\n }\n\n struct BridgeProof {\n uint96 timestamp;\n address relayer;\n }\n\n // ============ Events ============\n\n event BridgeRequested(\n bytes32 indexed transactionId,\n address indexed sender,\n bytes request,\n uint32 destChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n bool sendChainGas\n );\n event BridgeRelayed(\n bytes32 indexed transactionId,\n address indexed relayer,\n address indexed to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n );\n event BridgeProofProvided(bytes32 indexed transactionId, address indexed relayer, bytes32 transactionHash);\n event BridgeProofDisputed(bytes32 indexed transactionId, address indexed relayer);\n event BridgeDepositClaimed(\n bytes32 indexed transactionId, address indexed relayer, address indexed to, address token, uint256 amount\n );\n event BridgeDepositRefunded(bytes32 indexed transactionId, address indexed to, address token, uint256 amount);\n\n // ============ Methods ============\n\n struct BridgeParams {\n uint32 dstChainId;\n address sender;\n address to;\n address originToken;\n address destToken;\n uint256 originAmount; // should include protocol fee (if any)\n uint256 destAmount; // should include relayer fee\n bool sendChainGas;\n uint256 deadline;\n }\n\n /// @notice Initiates bridge on origin chain to be relayed by off-chain relayer\n /// @param params The parameters required to bridge\n function bridge(BridgeParams memory params) external payable;\n\n /// @notice Relays destination side of bridge transaction by off-chain relayer\n /// @param request The encoded bridge transaction to relay on destination chain\n function relay(bytes memory request) external payable;\n\n /// @notice Provides proof on origin side that relayer provided funds on destination side of bridge transaction\n /// @param request The encoded bridge transaction to prove on origin chain\n /// @param destTxHash The destination tx hash proving bridge transaction was relayed\n function prove(bytes memory request, bytes32 destTxHash) external;\n\n /// @notice Completes bridge transaction on origin chain by claiming originally deposited capital\n /// @param request The encoded bridge transaction to claim on origin chain\n /// @param to The recipient address of the funds\n function claim(bytes memory request, address to) external;\n\n /// @notice Disputes an outstanding proof in case relayer provided dest chain tx is invalid\n /// @param transactionId The transaction id associated with the encoded bridge transaction to dispute\n function dispute(bytes32 transactionId) external;\n\n /// @notice Refunds an outstanding bridge transaction in case optimistic bridging failed\n /// @param request The encoded bridge transaction to refund\n function refund(bytes memory request) external;\n\n // ============ Views ============\n\n /// @notice Decodes bridge request into a bridge transaction\n /// @param request The bridge request to decode\n function getBridgeTransaction(bytes memory request) external pure returns (BridgeTransaction memory);\n\n /// @notice Checks if the dispute period has passed so bridge deposit can be claimed\n /// @param transactionId The transaction id associated with the encoded bridge transaction to check\n /// @param relayer The address of the relayer attempting to claim\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool);\n}\n\n// contracts/libs/Errors.sol\n\nerror DeadlineExceeded();\nerror DeadlineNotExceeded();\nerror DeadlineTooShort();\nerror InsufficientOutputAmount();\n\nerror MsgValueIncorrect();\nerror PoolNotFound();\nerror TokenAddressMismatch();\nerror TokenNotContract();\nerror TokenNotETH();\nerror TokensIdentical();\n\nerror ChainIncorrect();\nerror AmountIncorrect();\nerror ZeroAddress();\n\nerror DisputePeriodNotPassed();\nerror DisputePeriodPassed();\nerror SenderIncorrect();\nerror StatusIncorrect();\nerror TransactionIdIncorrect();\nerror TransactionRelayed();\n\n// lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\n/**\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Address.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error AddressInsufficientBalance(address account);\n\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedInnerCall();\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance \u003c amount) {\n revert AddressInsufficientBalance(address(this));\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert FailedInnerCall();\n }\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {FailedInnerCall} error.\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance \u003c value) {\n revert AddressInsufficientBalance(address(this));\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n * unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 \u0026\u0026 target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {FailedInnerCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n */\n function _revert(bytes memory returndata) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length \u003e 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert FailedInnerCall();\n }\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/Context.sol\n\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position is the index of the value in the `values` array plus 1.\n // Position 0 is used to mean a value is not in the set.\n mapping(bytes32 value =\u003e uint256) _positions;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._positions[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We cache the value's position to prevent multiple reads from the same storage slot\n uint256 position = set._positions[value];\n\n if (position != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 valueIndex = position - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (valueIndex != lastIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the lastValue to the index where the value to delete is\n set._values[valueIndex] = lastValue;\n // Update the tracked position of the lastValue (that was just moved)\n set._positions[lastValue] = position;\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the tracked position for the deleted slot\n delete set._positions[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._positions[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n\n// lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance \u003c requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data);\n if (returndata.length != 0 \u0026\u0026 !abi.decode(returndata, (bool))) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return success \u0026\u0026 (returndata.length == 0 || abi.decode(returndata, (bool))) \u0026\u0026 address(token).code.length \u003e 0;\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/AccessControl.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address account =\u003e bool) hasRole;\n bytes32 adminRole;\n }\n\n mapping(bytes32 role =\u003e RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with an {AccessControlUnauthorizedAccount} error including the required role.\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n return _roles[role].hasRole[account];\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n * is missing `role`.\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert AccessControlUnauthorizedAccount(account, role);\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n if (callerConfirmation != _msgSender()) {\n revert AccessControlBadConfirmation();\n }\n\n _revokeRole(role, callerConfirmation);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n if (!hasRole(role, account)) {\n _roles[role].hasRole[account] = true;\n emit RoleGranted(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n if (hasRole(role, account)) {\n _roles[role].hasRole[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n return true;\n } else {\n return false;\n }\n }\n}\n\n// contracts/libs/UniversalToken.sol\n\nlibrary UniversalTokenLib {\n using SafeERC20 for IERC20;\n\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /// @notice Transfers tokens to the given account. Reverts if transfer is not successful.\n /// @dev This might trigger fallback, if ETH is transferred to the contract.\n /// Make sure this can not lead to reentrancy attacks.\n function universalTransfer(address token, address to, uint256 value) internal {\n // Don't do anything, if need to send tokens to this address\n if (to == address(this)) return;\n // Don't do anything, if trying to send zero value\n if (value == 0) return;\n if (token == ETH_ADDRESS) {\n /// @dev Note: this can potentially lead to executing code in `to`.\n // solhint-disable-next-line avoid-low-level-calls\n (bool success,) = to.call{value: value}(\"\");\n require(success, \"ETH transfer failed\");\n } else {\n IERC20(token).safeTransfer(to, value);\n }\n }\n\n /// @notice Issues an infinite allowance to the spender, if the current allowance is insufficient\n /// to spend the given amount.\n function universalApproveInfinity(address token, address spender, uint256 amountToSpend) internal {\n // ETH Chad doesn't require your approval\n if (token == ETH_ADDRESS) return;\n // No-op if allowance is already sufficient\n uint256 allowance = IERC20(token).allowance(address(this), spender);\n if (allowance \u003e= amountToSpend) return;\n // Otherwise, reset approval to 0 and set to max allowance\n if (allowance \u003e 0) IERC20(token).safeDecreaseAllowance(spender, allowance);\n IERC20(token).safeIncreaseAllowance(spender, type(uint256).max);\n }\n\n /// @notice Returns the balance of the given token (or native ETH) for the given account.\n function universalBalanceOf(address token, address account) internal view returns (uint256) {\n if (token == ETH_ADDRESS) {\n return account.balance;\n } else {\n return IERC20(token).balanceOf(account);\n }\n }\n\n /// @dev Checks that token is a contract and not ETH_ADDRESS.\n function assertIsContract(address token) internal view {\n // Check that ETH_ADDRESS was not used (in case this is a predeploy on any of the chains)\n if (token == UniversalTokenLib.ETH_ADDRESS) revert TokenNotContract();\n // Check that token is not an EOA\n if (token.code.length == 0) revert TokenNotContract();\n }\n}\n\n// lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\n\n// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 role =\u003e EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {AccessControl-_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool granted = super._grantRole(role, account);\n if (granted) {\n _roleMembers[role].add(account);\n }\n return granted;\n }\n\n /**\n * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n bool revoked = super._revokeRole(role, account);\n if (revoked) {\n _roleMembers[role].remove(account);\n }\n return revoked;\n }\n}\n\n// contracts/Admin.sol\n\ncontract Admin is IAdmin, AccessControlEnumerable {\n using UniversalTokenLib for address;\n\n bytes32 public constant RELAYER_ROLE = keccak256(\"RELAYER_ROLE\");\n bytes32 public constant REFUNDER_ROLE = keccak256(\"REFUNDER_ROLE\");\n bytes32 public constant GUARD_ROLE = keccak256(\"GUARD_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n\n uint256 public constant FEE_BPS = 1e6;\n uint256 public constant FEE_RATE_MAX = 0.01e6; // max 1% on origin amount\n\n /// @notice Protocol fee rate taken on origin amount deposited in origin chain\n uint256 public protocolFeeRate;\n\n /// @notice Protocol fee amounts accumulated\n mapping(address =\u003e uint256) public protocolFees;\n\n /// @notice Chain gas amount to forward as rebate if requested\n uint256 public chainGasAmount;\n\n constructor(address _owner) {\n _grantRole(DEFAULT_ADMIN_ROLE, _owner);\n }\n\n function setProtocolFeeRate(uint256 newFeeRate) external onlyRole(GOVERNOR_ROLE) {\n require(newFeeRate \u003c= FEE_RATE_MAX, \"newFeeRate \u003e max\");\n uint256 oldFeeRate = protocolFeeRate;\n protocolFeeRate = newFeeRate;\n emit FeeRateUpdated(oldFeeRate, newFeeRate);\n }\n\n function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {\n uint256 feeAmount = protocolFees[token];\n if (feeAmount == 0) return; // skip if no accumulated fees\n\n protocolFees[token] = 0;\n token.universalTransfer(recipient, feeAmount);\n emit FeesSwept(token, recipient, feeAmount);\n }\n\n function setChainGasAmount(uint256 newChainGasAmount) external onlyRole(GOVERNOR_ROLE) {\n uint256 oldChainGasAmount = chainGasAmount;\n chainGasAmount = newChainGasAmount;\n emit ChainGasAmountUpdated(oldChainGasAmount, newChainGasAmount);\n }\n}\n\n// contracts/FastBridge.sol\n\ncontract FastBridge is IFastBridge, Admin {\n using SafeERC20 for IERC20;\n using UniversalTokenLib for address;\n\n /// @notice Dispute period for relayed transactions\n uint256 public constant DISPUTE_PERIOD = 30 minutes;\n\n /// @notice Delay for a transaction after which it could be permisionlessly refunded\n uint256 public constant REFUND_DELAY = 7 days;\n\n /// @notice Minimum deadline period to relay a requested bridge transaction\n uint256 public constant MIN_DEADLINE_PERIOD = 30 minutes;\n\n enum BridgeStatus {\n NULL, // doesn't exist yet\n REQUESTED,\n RELAYER_PROVED,\n RELAYER_CLAIMED,\n REFUNDED\n }\n\n /// @notice Status of the bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeStatus) public bridgeStatuses;\n /// @notice Proof of relayed bridge tx on origin chain\n mapping(bytes32 =\u003e BridgeProof) public bridgeProofs;\n /// @notice Whether bridge has been relayed on destination chain\n mapping(bytes32 =\u003e bool) public bridgeRelays;\n\n /// @dev to prevent replays\n uint256 public nonce;\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @notice Pulls a requested token from the user to the requested recipient.\n /// @dev Be careful of re-entrancy issues when msg.value \u003e 0 and recipient != address(this)\n function _pullToken(address recipient, address token, uint256 amount) internal returns (uint256 amountPulled) {\n if (token != UniversalTokenLib.ETH_ADDRESS) {\n token.assertIsContract();\n // Record token balance before transfer\n amountPulled = IERC20(token).balanceOf(recipient);\n // Token needs to be pulled only if msg.value is zero\n // This way user can specify WETH as the origin asset\n IERC20(token).safeTransferFrom(msg.sender, recipient, amount);\n // Use the difference between the recorded balance and the current balance as the amountPulled\n amountPulled = IERC20(token).balanceOf(recipient) - amountPulled;\n } else {\n // Otherwise, we need to check that ETH amount matches msg.value\n if (amount != msg.value) revert MsgValueIncorrect();\n // Transfer value to recipient if not this address\n if (recipient != address(this)) token.universalTransfer(recipient, amount);\n // We will forward msg.value in the external call later, if recipient is not this contract\n amountPulled = msg.value;\n }\n }\n\n /// @inheritdoc IFastBridge\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n /// @inheritdoc IFastBridge\n function bridge(BridgeParams memory params) external payable {\n // check bridge params\n if (params.dstChainId == block.chainid) revert ChainIncorrect();\n if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect();\n if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress();\n if (params.deadline \u003c block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort();\n\n // transfer tokens to bridge contract\n // @dev use returned originAmount in request in case of transfer fees\n uint256 originAmount = _pullToken(address(this), params.originToken, params.originAmount);\n\n // track amount of origin token owed to protocol\n uint256 originFeeAmount;\n if (protocolFeeRate \u003e 0) originFeeAmount = (originAmount * protocolFeeRate) / FEE_BPS;\n originAmount -= originFeeAmount; // remove from amount used in request as not relevant for relayers\n\n // set status to requested\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: originAmount,\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n bytes32 transactionId = keccak256(request);\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n /// @inheritdoc IFastBridge\n function relay(bytes memory request) external payable onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n if (transaction.destChainId != uint32(block.chainid)) revert ChainIncorrect();\n\n // check haven't exceeded deadline for relay to happen\n if (block.timestamp \u003e transaction.deadline) revert DeadlineExceeded();\n\n // mark bridge transaction as relayed\n if (bridgeRelays[transactionId]) revert TransactionRelayed();\n bridgeRelays[transactionId] = true;\n\n // transfer tokens to recipient on destination chain and gas rebate if requested\n address to = transaction.destRecipient;\n address token = transaction.destToken;\n uint256 amount = transaction.destAmount;\n\n uint256 rebate = chainGasAmount;\n if (!transaction.sendChainGas) {\n // forward erc20\n rebate = 0;\n _pullToken(to, token, amount);\n } else if (token == UniversalTokenLib.ETH_ADDRESS) {\n // lump in gas rebate into amount in native gas token\n _pullToken(to, token, amount + rebate);\n } else {\n // forward erc20 then forward gas rebate in native gas token\n _pullToken(to, token, amount);\n _pullToken(to, UniversalTokenLib.ETH_ADDRESS, rebate);\n }\n\n emit BridgeRelayed(\n transactionId,\n msg.sender,\n to,\n transaction.originChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n rebate\n );\n }\n\n /// @inheritdoc IFastBridge\n function prove(bytes memory request, bytes32 destTxHash) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n // update bridge tx status given proof provided\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_PROVED;\n bridgeProofs[transactionId] = BridgeProof({timestamp: uint96(block.timestamp), relayer: msg.sender}); // overflow ok\n\n emit BridgeProofProvided(transactionId, msg.sender, destTxHash);\n }\n\n /// @notice Calculates time since proof submitted\n /// @dev proof.timestamp stores casted uint96(block.timestamp) block timestamps for gas optimization\n /// _timeSince(proof) can accomodate rollover case when block.timestamp \u003e type(uint96).max but\n /// proof.timestamp \u003c type(uint96).max via unchecked statement\n /// @param proof The bridge proof\n /// @return delta Time delta since proof submitted\n function _timeSince(BridgeProof memory proof) internal view returns (uint256 delta) {\n unchecked {\n delta = uint96(block.timestamp) - proof.timestamp;\n }\n }\n\n /// @inheritdoc IFastBridge\n function canClaim(bytes32 transactionId, address relayer) external view returns (bool) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != relayer) revert SenderIncorrect();\n return _timeSince(proof) \u003e DISPUTE_PERIOD;\n }\n\n /// @inheritdoc IFastBridge\n function claim(bytes memory request, address to) external onlyRole(RELAYER_ROLE) {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n // update bridge tx status if able to claim origin collateral\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n\n BridgeProof memory proof = bridgeProofs[transactionId];\n if (proof.relayer != msg.sender) revert SenderIncorrect();\n if (_timeSince(proof) \u003c= DISPUTE_PERIOD) revert DisputePeriodNotPassed();\n\n bridgeStatuses[transactionId] = BridgeStatus.RELAYER_CLAIMED;\n\n // update protocol fees if origin fee amount exists\n if (transaction.originFeeAmount \u003e 0) protocolFees[transaction.originToken] += transaction.originFeeAmount;\n\n // transfer origin collateral less fee to specified address\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositClaimed(transactionId, msg.sender, to, token, amount);\n }\n\n /// @inheritdoc IFastBridge\n function dispute(bytes32 transactionId) external onlyRole(GUARD_ROLE) {\n if (bridgeStatuses[transactionId] != BridgeStatus.RELAYER_PROVED) revert StatusIncorrect();\n if (_timeSince(bridgeProofs[transactionId]) \u003e DISPUTE_PERIOD) revert DisputePeriodPassed();\n\n // @dev relayer gets slashed effectively if dest relay has gone thru\n bridgeStatuses[transactionId] = BridgeStatus.REQUESTED;\n delete bridgeProofs[transactionId];\n\n emit BridgeProofDisputed(transactionId, msg.sender);\n }\n\n /// @inheritdoc IFastBridge\n function refund(bytes memory request) external {\n bytes32 transactionId = keccak256(request);\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n\n if (hasRole(REFUNDER_ROLE, msg.sender)) {\n // Refunder can refund if deadline has passed\n if (block.timestamp \u003c= transaction.deadline) revert DeadlineNotExceeded();\n } else {\n // Permissionless refund is allowed after REFUND_DELAY\n if (block.timestamp \u003c= transaction.deadline + REFUND_DELAY) revert DeadlineNotExceeded();\n }\n\n // set status to refunded if still in requested state\n if (bridgeStatuses[transactionId] != BridgeStatus.REQUESTED) revert StatusIncorrect();\n bridgeStatuses[transactionId] = BridgeStatus.REFUNDED;\n\n // transfer origin collateral back to original sender\n address to = transaction.originSender;\n address token = transaction.originToken;\n uint256 amount = transaction.originAmount + transaction.originFeeAmount;\n token.universalTransfer(to, amount);\n\n emit BridgeDepositRefunded(transactionId, to, token, amount);\n }\n}\n\n// test/FastBridgeMock.sol\n\ncontract FastBridgeMock is IFastBridge, Admin {\n // @dev the block the contract was deployed at\n uint256 public immutable deployBlock;\n\n constructor(address _owner) Admin(_owner) {\n deployBlock = block.number;\n }\n\n /// @dev to prevent replays\n uint256 public nonce;\n\n function getBridgeTransaction(bytes memory request) public pure returns (BridgeTransaction memory) {\n return abi.decode(request, (BridgeTransaction));\n }\n\n // used for testing in go.\n // see: https://ethereum.stackexchange.com/questions/21155/how-to-expose-enum-in-solidity-contract\n // make sure to update fastbridge/status.go if this changes\n // or underliyng enum changes.\n //\n // TODO: a foundry test should be added to ensure this is always in sync.\n function getEnumKeyByValue(FastBridge.BridgeStatus keyValue) public pure returns (string memory) {\n if (FastBridge.BridgeStatus.NULL == keyValue) return \"NULL\";\n if (FastBridge.BridgeStatus.REQUESTED == keyValue) return \"REQUESTED\";\n if (FastBridge.BridgeStatus.RELAYER_PROVED == keyValue) return \"RELAYER_PROVED\";\n if (FastBridge.BridgeStatus.RELAYER_CLAIMED == keyValue) return \"RELAYER_CLAIMED\";\n if (FastBridge.BridgeStatus.REFUNDED == keyValue) return \"REFUNDED\";\n return \"\";\n }\n\n function mockBridgeRequest(bytes32 transactionId, address sender, BridgeParams memory params) external {\n uint256 originFeeAmount = (params.originAmount * protocolFeeRate) / FEE_BPS;\n params.originAmount -= originFeeAmount;\n\n bytes memory request = abi.encode(\n BridgeTransaction({\n originChainId: uint32(block.chainid),\n destChainId: params.dstChainId,\n originSender: params.sender,\n destRecipient: params.to,\n originToken: params.originToken,\n destToken: params.destToken,\n originAmount: params.originAmount, // includes relayer fee\n destAmount: params.destAmount,\n originFeeAmount: originFeeAmount,\n sendChainGas: params.sendChainGas,\n deadline: params.deadline,\n nonce: nonce++ // increment nonce on every bridge\n })\n );\n\n emit BridgeRequested(\n transactionId,\n params.sender,\n request,\n params.dstChainId,\n params.originToken,\n params.destToken,\n params.originAmount,\n params.destAmount,\n params.sendChainGas\n );\n }\n\n function mockBridgeRequestRaw(bytes32 transactionId, address sender, bytes memory request) external {\n BridgeTransaction memory transaction = getBridgeTransaction(request);\n emit BridgeRequested(\n transactionId,\n transaction.originSender,\n request,\n transaction.destChainId,\n transaction.originToken,\n transaction.destToken,\n transaction.originAmount,\n transaction.destAmount,\n transaction.sendChainGas\n );\n }\n\n function mockBridgeRelayer(\n bytes32 transactionId,\n address relayer,\n address to,\n uint32 originChainId,\n address originToken,\n address destToken,\n uint256 originAmount,\n uint256 destAmount,\n uint256 chainGasAmount\n )\n external\n {\n emit BridgeRelayed(\n transactionId, relayer, to, originChainId, originToken, destToken, originAmount, destAmount, chainGasAmount\n );\n }\n\n function bridge(BridgeParams memory params) external payable {\n revert(\"not implemented\");\n }\n\n function relay(bytes memory request) external payable {\n revert(\"not implemented\");\n }\n\n function prove(bytes memory request, bytes32 destTxHash) external {\n revert(\"not implemented\");\n }\n\n function canClaim(bytes32 transactionid, address relayer) external view returns (bool) {\n revert(\"not implemented\");\n }\n\n function claim(bytes memory request, address to) external {\n revert(\"not implemented\");\n }\n\n function dispute(bytes32 transactionId) external {\n revert(\"not implemented\");\n }\n\n function refund(bytes memory request) external {\n revert(\"not implemented\");\n }\n}\n","language":"Solidity","languageVersion":"0.8.20","compilerVersion":"0.8.20","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../ --evm-version=istanbul","srcMap":"51225:2551:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;51225:2551:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"51225:2551:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/FastBridgeMock.sol\":\"UniversalTokenLib\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/FastBridgeMock.sol\":{\"keccak256\":\"0x4fff59c4cd271340f4a824126cbe4ebe7c8dc20639e268edf42ff873af31f862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4d33ef4f98d2abd98b4bbcb403b27495c37843b37000bea9f48e533078144d84\",\"dweb:/ipfs/QmTMkQhtNJPVgpxiLnEG45Ww7xfXHMEoVQ5JdbEbaFXwwS\"]}},\"version\":1}"},"hashes":{}}} \ No newline at end of file diff --git a/services/rfq/e2e/setup_test.go b/services/rfq/e2e/setup_test.go index 11cc2aa62c..e638ccbc96 100644 --- a/services/rfq/e2e/setup_test.go +++ b/services/rfq/e2e/setup_test.go @@ -229,7 +229,10 @@ func (i *IntegrationSuite) setupRelayer() { metadata, rfqContract := i.manager.GetFastBridge(i.GetTestContext(), backend) txContext := backend.GetTxContext(i.GetTestContext(), metadata.OwnerPtr()) - tx, err := rfqContract.AddRelayer(txContext.TransactOpts, i.relayerWallet.Address()) + relayerRole, err := rfqContract.RELAYERROLE(&bind.CallOpts{Context: i.GetTestContext()}) + i.NoError(err) + + tx, err := rfqContract.GrantRole(txContext.TransactOpts, relayerRole, i.relayerWallet.Address()) i.NoError(err) backend.WaitForConfirmation(i.GetTestContext(), tx) diff --git a/services/rfq/relayer/relapi/suite_test.go b/services/rfq/relayer/relapi/suite_test.go index 879d682db4..39b51339fd 100644 --- a/services/rfq/relayer/relapi/suite_test.go +++ b/services/rfq/relayer/relapi/suite_test.go @@ -163,7 +163,11 @@ func (c *RelayerServerSuite) SetupSuite() { fastBridgeInstance, err := fastbridge.NewFastBridge(fastBridgeAddress, backend) c.Require().NoError(err) - tx, err = fastBridgeInstance.AddRelayer(auth, c.testWallet.Address()) + + relayerRole, err := fastBridgeInstance.RELAYERROLE(&bind.CallOpts{Context: c.GetTestContext()}) + c.NoError(err) + + tx, err = fastBridgeInstance.GrantRole(auth, relayerRole, c.testWallet.Address()) c.Require().NoError(err) backend.WaitForConfirmation(c.GetSuiteContext(), tx) From 79d038939ef5ba54f3e1637c0ae69e980e615a7b Mon Sep 17 00:00:00 2001 From: aureliusbtc <82057759+aureliusbtc@users.noreply.github.com> Date: Thu, 14 Mar 2024 14:27:02 +0000 Subject: [PATCH 17/29] extend metis (#2290) --- .../components/Maintenance/Events/MetisUpgrade.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/synapse-interface/components/Maintenance/Events/MetisUpgrade.tsx b/packages/synapse-interface/components/Maintenance/Events/MetisUpgrade.tsx index 20272264af..223a178bab 100644 --- a/packages/synapse-interface/components/Maintenance/Events/MetisUpgrade.tsx +++ b/packages/synapse-interface/components/Maintenance/Events/MetisUpgrade.tsx @@ -17,7 +17,7 @@ export const METIS_DOWNTIME_START_DATE = new Date( Date.UTC(2024, 2, 14, 1, 45, 0) ) export const METIS_DOWNTIME_END_DATE = new Date( - Date.UTC(2024, 2, 14, 13, 30, 0) + Date.UTC(2024, 2, 14, 16, 30, 0) ) export const MetisDowntimeBanner = () => { From fd9122b0f94ee5747fa7a020babfd974aaa62a84 Mon Sep 17 00:00:00 2001 From: aureliusbtc Date: Thu, 14 Mar 2024 14:30:37 +0000 Subject: [PATCH 18/29] Publish - @synapsecns/synapse-interface@0.9.3 --- packages/synapse-interface/CHANGELOG.md | 8 ++++++++ packages/synapse-interface/package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/synapse-interface/CHANGELOG.md b/packages/synapse-interface/CHANGELOG.md index c71b5b3fa5..20390d211c 100644 --- a/packages/synapse-interface/CHANGELOG.md +++ b/packages/synapse-interface/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.9.3](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.9.2...@synapsecns/synapse-interface@0.9.3) (2024-03-14) + +**Note:** Version bump only for package @synapsecns/synapse-interface + + + + + ## [0.9.2](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.9.1...@synapsecns/synapse-interface@0.9.2) (2024-03-14) **Note:** Version bump only for package @synapsecns/synapse-interface diff --git a/packages/synapse-interface/package.json b/packages/synapse-interface/package.json index beb14c40d8..07316fbf3a 100644 --- a/packages/synapse-interface/package.json +++ b/packages/synapse-interface/package.json @@ -1,6 +1,6 @@ { "name": "@synapsecns/synapse-interface", - "version": "0.9.2", + "version": "0.9.3", "private": true, "engines": { "node": ">=16.0.0" From e14071bf1014050036b5e2e0858aa1e84aad2e18 Mon Sep 17 00:00:00 2001 From: abtestingalpha <104046418+abtestingalpha@users.noreply.github.com> Date: Thu, 14 Mar 2024 10:01:47 -0500 Subject: [PATCH 19/29] fix(synapse-interface): deprecate unused dependencies (#2287) * Code cleanup * Move deps that are for development into devDeps * Remove unused deps * Remove deprecated code * lock file update --------- Co-authored-by: trajan0x <83933037+trajan0x@users.noreply.github.com> Co-authored-by: Trajan0x --- .../BridgeTransactionButton.tsx | 2 +- .../components/misc/ChainSlideOver.tsx | 157 ----------------- .../components/misc/TokenSlideOver.tsx | 158 ------------------ packages/synapse-interface/craco.config.js | 9 - packages/synapse-interface/package.json | 26 +-- .../pages/pool/poolManagement/Deposit.tsx | 4 +- .../pages/state-managed-bridge/index.tsx | 3 +- .../utils/checkCleanedValue.ts | 3 - .../synapse-interface/utils/displaySymbol.ts | 37 ---- .../utils/getOrderedChains.ts | 28 ---- .../utils/hooks/useDebounce.ts | 26 --- .../utils/hooks/useDebounce.tsx | 26 --- .../utils/hooks/useSettings.tsx | 9 - .../utils/hooks/useTxHistory.ts | 71 -------- .../utils/matchSymbolWithinPool.ts | 16 -- .../synapse-interface/utils/remove0xPrefix.ts | 9 - packages/synapse-interface/utils/toHexStr.ts | 3 - .../synapse-interface/utils/types/index.tsx | 2 +- .../utils/validateAndParseAddress.ts | 13 -- yarn.lock | 105 +++++++----- 20 files changed, 74 insertions(+), 633 deletions(-) delete mode 100644 packages/synapse-interface/components/misc/ChainSlideOver.tsx delete mode 100644 packages/synapse-interface/components/misc/TokenSlideOver.tsx delete mode 100644 packages/synapse-interface/craco.config.js delete mode 100644 packages/synapse-interface/utils/checkCleanedValue.ts delete mode 100644 packages/synapse-interface/utils/displaySymbol.ts delete mode 100644 packages/synapse-interface/utils/getOrderedChains.ts delete mode 100644 packages/synapse-interface/utils/hooks/useDebounce.ts delete mode 100644 packages/synapse-interface/utils/hooks/useDebounce.tsx delete mode 100644 packages/synapse-interface/utils/hooks/useSettings.tsx delete mode 100644 packages/synapse-interface/utils/hooks/useTxHistory.ts delete mode 100644 packages/synapse-interface/utils/matchSymbolWithinPool.ts delete mode 100644 packages/synapse-interface/utils/remove0xPrefix.ts delete mode 100644 packages/synapse-interface/utils/toHexStr.ts delete mode 100644 packages/synapse-interface/utils/validateAndParseAddress.ts diff --git a/packages/synapse-interface/components/StateManagedBridge/BridgeTransactionButton.tsx b/packages/synapse-interface/components/StateManagedBridge/BridgeTransactionButton.tsx index c10e98aa6a..a9c9e0ec9c 100644 --- a/packages/synapse-interface/components/StateManagedBridge/BridgeTransactionButton.tsx +++ b/packages/synapse-interface/components/StateManagedBridge/BridgeTransactionButton.tsx @@ -5,7 +5,7 @@ import { EMPTY_BRIDGE_QUOTE, EMPTY_BRIDGE_QUOTE_ZERO } from '@/constants/bridge' import { RootState } from '@/store/store' import { useAccount, useNetwork, useSwitchNetwork } from 'wagmi' import { useEffect, useState } from 'react' -import { isAddress } from '@ethersproject/address' +import { isAddress } from 'viem' import { useConnectModal } from '@rainbow-me/rainbowkit' import { stringToBigInt } from '@/utils/bigint/format' diff --git a/packages/synapse-interface/components/misc/ChainSlideOver.tsx b/packages/synapse-interface/components/misc/ChainSlideOver.tsx deleted file mode 100644 index 5d78af704e..0000000000 --- a/packages/synapse-interface/components/misc/ChainSlideOver.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import { useCallback, useEffect, useState } from 'react' -import Fuse from 'fuse.js' -import { useKeyPress } from '@hooks/useKeyPress' -import * as CHAINS from '@constants/chains/master' -import { SelectSpecificNetworkButton } from '@components/buttons/SelectSpecificNetworkButton' -import SlideSearchBox from '@pages/bridge/SlideSearchBox' -import { DrawerButton } from '@components/buttons/DrawerButton' -import { useNetwork } from 'wagmi' -import { DisplayType } from '@/pages/bridge/DisplayType' -import { sortChains } from '@constants/chains' - -export const ChainSlideOver = ({ - isOrigin, - chains, - chainId, - onChangeChain, - setDisplayType, -}: { - isOrigin: boolean - chains: string[] - chainId: number - onChangeChain: (chainId: number, flip: boolean, type: 'from' | 'to') => void - setDisplayType: (v: DisplayType) => void -}) => { - const { chain } = useNetwork() - const [currentIdx, setCurrentIdx] = useState(-1) - const [searchStr, setSearchStr] = useState('') - const [networks, setNetworks] = useState([]) - const fuse = new Fuse(networks, { - includeScore: true, - threshold: 0.0, - keys: [ - { - name: 'name', - weight: 2, - }, - 'chainShortName', - 'chainId', - 'nativeCurrency', - ], - }) - // let networks: ChainInfo[] = [] - - const dataId = isOrigin - ? 'bridge-origin-chain-list' - : 'bridge-destination-chain-list' - - useEffect(() => { - let tempNetworks = [] - Object.values(CHAINS).map((chain) => { - if (isOrigin || (!isOrigin && chains?.includes(String(chain.id)))) { - tempNetworks.push(chain) - } - }) - tempNetworks = sortChains(tempNetworks) - if (searchStr?.length > 0) { - tempNetworks = fuse.search(searchStr).map((i) => i.item) - } - setNetworks(tempNetworks) - }, [chain, searchStr]) - - const escPressed = useKeyPress('Escape') - const arrowUp = useKeyPress('ArrowUp') - const arrowDown = useKeyPress('ArrowDown') - const enterPressed = useKeyPress('Enter') - - const onClose = useCallback(() => { - setCurrentIdx(-1) - setDisplayType(DisplayType.DEFAULT) - }, [setDisplayType]) - - const escFunc = () => { - if (escPressed) { - onClose() - } - } - const arrowDownFunc = () => { - const nextIdx = currentIdx + 1 - if (arrowDown && nextIdx < networks.length) { - setCurrentIdx(nextIdx) - } - } - - const arrowUpFunc = () => { - const nextIdx = currentIdx - 1 - if (arrowUp && -1 < nextIdx) { - setCurrentIdx(nextIdx) - } - } - - const enterPressedFunc = () => { - if (enterPressed && currentIdx > -1) { - const currentChain = networks[currentIdx] - onChangeChain(currentChain.chainId, false, isOrigin ? 'from' : 'to') - onClose() - } - } - const onSearch = (str: string) => { - setSearchStr(str) - setCurrentIdx(-1) - } - - useEffect(arrowDownFunc, [arrowDown]) - useEffect(escFunc, [escPressed]) - useEffect(arrowUpFunc, [arrowUp]) - useEffect(enterPressedFunc, [enterPressed]) - - return ( -
-
-
- - -
-
-
- {networks.map(({ id: mapChainId }, idx) => { - let onClickSpecificNetwork - if (chainId === mapChainId) { - onClickSpecificNetwork = () => console.log('INCEPTION') // I think this case is obsolete - } else { - onClickSpecificNetwork = () => { - onChangeChain(mapChainId, false, isOrigin ? 'from' : 'to') - onClose() - } - } - return ( - - ) - })} - {searchStr && ( -
- No other results found for{' '} - {searchStr}. -
- Want to see a chain supported on Synapse? Submit a request{' '} - - here - -
-
- )} -
-
- ) -} diff --git a/packages/synapse-interface/components/misc/TokenSlideOver.tsx b/packages/synapse-interface/components/misc/TokenSlideOver.tsx deleted file mode 100644 index dc301640ec..0000000000 --- a/packages/synapse-interface/components/misc/TokenSlideOver.tsx +++ /dev/null @@ -1,158 +0,0 @@ -import { useEffect, useState } from 'react' -import Fuse from 'fuse.js' -import { Zero } from '@ethersproject/constants' -import { useKeyPress } from '@hooks/useKeyPress' -import TokenMenuItem from '@pages/bridge/TokenMenuItem' -import SlideSearchBox from '@pages/bridge/SlideSearchBox' -import { DrawerButton } from '@components/buttons/DrawerButton' -import { sortTokens } from '@constants/tokens' - -import { Token } from '@/utils/types' -import { DisplayType } from '@/pages/bridge/DisplayType' - -export const TokenSlideOver = ({ - isOrigin, - tokens = [], - chainId, - selectedToken, - setDisplayType, - handleTokenChange, -}: { - isOrigin: boolean - tokens: any[] - chainId: number - selectedToken: Token - setDisplayType: (v: DisplayType) => void - handleTokenChange: (token: Token, type: 'from' | 'to') => void -}) => { - const [currentIdx, setCurrentIdx] = useState(-1) - const [searchStr, setSearchStr] = useState('') - let tokenList: any[] = [] - if (!isOrigin && tokens?.length > 0) { - tokens.map((token) => { - tokenList.push({ token, balance: Zero }) - }) - } else { - tokenList = tokens - } - tokenList = sortTokens(tokenList) - - const fuse = new Fuse(tokenList, { - includeScore: true, - threshold: 0.0, - keys: [ - { - name: 'token.symbol', - weight: 2, - }, - `token.addresses.${chainId}`, - 'token.name', - ], - }) - - if (searchStr?.length > 0) { - tokenList = fuse.search(searchStr).map((i) => i.item) - } - const escPressed = useKeyPress('Escape') - const arrowUp = useKeyPress('ArrowUp') - const arrowDown = useKeyPress('ArrowDown') - const enterPressed = useKeyPress('Enter') - - function onClose() { - setCurrentIdx(-1) - setDisplayType(DisplayType.DEFAULT) - } - - function onMenuItemClick(coin: any) { - handleTokenChange(coin, isOrigin ? 'from' : 'to') - onClose() - } - - function escFunc() { - if (escPressed) { - onClose() - } - } - - useEffect(escFunc, [escPressed]) - - function arrowDownFunc() { - const nextIdx = currentIdx + 1 - if (arrowDown && nextIdx < tokenList.length) { - setCurrentIdx(nextIdx) - } - } - - useEffect(arrowDownFunc, [arrowDown]) - - function arrowUpFunc() { - const nextIdx = currentIdx - 1 - if (arrowUp && -1 < nextIdx) { - setCurrentIdx(nextIdx) - } - } - - useEffect(arrowUpFunc, [arrowUp]) - - function enterPressedFunc() { - if (enterPressed && currentIdx > -1) { - onMenuItemClick(tokenList[currentIdx]) - } - } - - useEffect(enterPressedFunc, [enterPressed]) - - function onSearch(str: string) { - setSearchStr(str) - setCurrentIdx(-1) - } - - return ( -
-
-
- - -
-
-
- {tokenList.map((token, idx) => ( - { - onMenuItemClick(token.token) - }} - /> - ))} - {searchStr && ( -
- No other results found for{' '} - {searchStr}. -
- Want to see a token supported on Synapse? Submit a request{' '} - - here - -
-
- )} -
-
- ) -} diff --git a/packages/synapse-interface/craco.config.js b/packages/synapse-interface/craco.config.js deleted file mode 100644 index 435890e604..0000000000 --- a/packages/synapse-interface/craco.config.js +++ /dev/null @@ -1,9 +0,0 @@ -const CracoAlias = require('craco-alias') - -module.exports = { - plugins: [ - { - plugin: CracoAlias, - }, - ], -} diff --git a/packages/synapse-interface/package.json b/packages/synapse-interface/package.json index 07316fbf3a..d2ac24f430 100644 --- a/packages/synapse-interface/package.json +++ b/packages/synapse-interface/package.json @@ -25,17 +25,9 @@ }, "dependencies": { "@cloudflare/next-on-pages": "1", - "@depay/web3-mock": "^14.0.0", - "@ethersproject/abi": "5.7.0", - "@ethersproject/address": "5.7.0", "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", "@ethersproject/providers": "5.7.2", "@ethersproject/units": "5.7.0", - "@graphql-codegen/typescript-rtk-query": "^2.4.1", "@headlessui/react": "^1.7.15", "@heroicons/react": "1.0.6", "@rainbow-me/rainbowkit": "^1.0.4", @@ -46,7 +38,6 @@ "@tailwindcss/aspect-ratio": "^0.4.2", "@tailwindcss/forms": "^0.5.3", "@tailwindcss/typography": "^0.5.9", - "@testing-library/cypress": "^9.0.0", "@types/node": "18.14.2", "@types/react": "18.0.28", "@types/react-dom": "18.0.11", @@ -54,21 +45,13 @@ "@visx/chord": "^3.0.0", "@visx/shape": "^3.0.0", "@wagmi/core": "^1.4.12", - "add": "^2.0.6", - "autoprefixer": "^10.4.13", "babel-plugin-transform-bigint": "^1.0.32", - "bignumber": "^1.1.0", - "cypress": "^13.0.0", - "dayjs": "^1.11.7", "eslint": "^8.37.0", "eslint-config-next": "^13.5.6", "ethers": "5.7.2", "fuse.js": "^6.6.2", "graphql": "^16.7.1", - "graphql-request": "^6.1.0", - "keccak": "^3.0.3", "lodash": "^4.17.21", - "lodash.debounce": "^4.0.8", "logrocket": "^7.0.0", "logrocket-react": "^6.0.3", "next": "^13.5.6", @@ -82,16 +65,13 @@ "react-redux": "^8.1.0", "react-spring": "^9.7.1", "redux-persist": "^6.0.0", - "start-server-and-test": "^2.0.0", "swr": "1.3.0", "tailwind-merge": "^1.10.0", "tailwind-scrollbar-hide": "^1.1.7", "tailwindcss": "^3.4.1", "tailwindcss-border-gradient-radius": "^3.0.1", - "tiny-warning": "^1.0.0", "typescript": "5.1.6", "use-persisted-state": "^0.3.3", - "use-window-focus": "^1.4.2", "viem": "^1.18.1", "wagmi": "^1.4.12", "yarn": "^1.22.19" @@ -116,9 +96,15 @@ "license": "ISC", "keywords": [], "devDependencies": { + "cypress": "^13.0.0", + "dayjs": "^1.11.7", + "@depay/web3-mock": "^14.0.0", + "@testing-library/cypress": "^9.0.0", + "start-server-and-test": "^2.0.0", "@graphql-codegen/cli": "5.0.0", "@graphql-codegen/client-preset": "4.1.0", "@graphql-codegen/introspection": "4.0.0", + "@graphql-codegen/typescript-rtk-query": "^2.4.1", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^14.0.0", "@types/redux-persist": "^4.3.1", diff --git a/packages/synapse-interface/pages/pool/poolManagement/Deposit.tsx b/packages/synapse-interface/pages/pool/poolManagement/Deposit.tsx index c932b46a85..49e8a5f414 100644 --- a/packages/synapse-interface/pages/pool/poolManagement/Deposit.tsx +++ b/packages/synapse-interface/pages/pool/poolManagement/Deposit.tsx @@ -8,7 +8,6 @@ import { deposit, emptyPoolDeposit, } from '@/utils/actions/approveAndDeposit' -import { getAddress } from '@ethersproject/address' import { fetchBalance, waitForTransaction } from '@wagmi/core' import { getSwapDepositContractFields } from '@/utils/getSwapDepositContractFields' import { calculatePriceImpact } from '@/utils/priceImpact' @@ -20,7 +19,7 @@ import { useDispatch } from 'react-redux' import { DepositTokenInput } from '@components/TokenInput' import { Token } from '@types' import { Address } from '@wagmi/core' -import { zeroAddress } from 'viem' + import { resetPoolDeposit, setDepositQuote, @@ -41,6 +40,7 @@ import { txErrorHandler } from '@/utils/txErrorHandler' import LoadingTokenInput from '@components/loading/LoadingTokenInput' import PriceImpactDisplay from '../components/PriceImpactDisplay' import DepositButton from './DepositButton' +import { getAddress, zeroAddress } from 'viem' export const DEFAULT_DEPOSIT_QUOTE = { priceImpact: 0n, diff --git a/packages/synapse-interface/pages/state-managed-bridge/index.tsx b/packages/synapse-interface/pages/state-managed-bridge/index.tsx index 9cb71d6685..9c298791f6 100644 --- a/packages/synapse-interface/pages/state-managed-bridge/index.tsx +++ b/packages/synapse-interface/pages/state-managed-bridge/index.tsx @@ -58,11 +58,10 @@ import SettingsSlideOver from '@/components/StateManagedBridge/SettingsSlideOver import Button from '@/components/ui/tailwind/Button' import { SettingsIcon } from '@/components/icons/SettingsIcon' import { DestinationAddressInput } from '@/components/StateManagedBridge/DestinationAddressInput' -import { isAddress } from '@ethersproject/address' import { BridgeTransactionButton } from '@/components/StateManagedBridge/BridgeTransactionButton' import ExplorerToastLink from '@/components/ExplorerToastLink' -import { Address, zeroAddress, createPublicClient, http } from 'viem' import { polygon } from 'viem/chains' +import { Address, zeroAddress, isAddress } from 'viem' import { stringToBigInt } from '@/utils/bigint/format' import { Warning } from '@/components/Warning' import { useAppDispatch } from '@/store/hooks' diff --git a/packages/synapse-interface/utils/checkCleanedValue.ts b/packages/synapse-interface/utils/checkCleanedValue.ts deleted file mode 100644 index 1ff094bb81..0000000000 --- a/packages/synapse-interface/utils/checkCleanedValue.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const checkCleanedValue = (cleanedValue) => { - return cleanedValue === 0 || cleanedValue === '' || isNaN(+cleanedValue) -} diff --git a/packages/synapse-interface/utils/displaySymbol.ts b/packages/synapse-interface/utils/displaySymbol.ts deleted file mode 100644 index e7ee671073..0000000000 --- a/packages/synapse-interface/utils/displaySymbol.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { SYNJEWEL } from '@constants/tokens/bridgeable' -import * as CHAINS from '@constants/chains/master' - -import { Token } from '@/utils/types' -/** - * In our `constants/tokens/master.tsx` file, we combine multiple stablecoin - * contracts like USDC/USDT into multiple networks. - * However, on chains like Avalanche, their contract addresses correspond to - * other symbols (USDC.e/USDT.e). This helper function decorates a symbol - * according to what it should reflect. We do this so we don't break any - * downstream logic from tokens. - * - * - * CHECK IF CAN DELETE ONCE SWAP IMPLEMENTED - */ - -export const displaySymbol = (chainId: number, token: Token) => { - if (!token?.symbol) { - return '' - } - if (token.symbol === SYNJEWEL.symbol) { - return 'synJEWEL' - } else if (chainId === CHAINS.AVALANCHE.id) { - switch (token.symbol) { - // case 'USDC': - // return 'USDC.e' - // case 'USDT': - // return 'USDT.e' - case 'DAI': - return 'DAI.e' - default: - return token.symbol - } - } else { - return token.symbol - } -} diff --git a/packages/synapse-interface/utils/getOrderedChains.ts b/packages/synapse-interface/utils/getOrderedChains.ts deleted file mode 100644 index bbdd7f5b6d..0000000000 --- a/packages/synapse-interface/utils/getOrderedChains.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { ORDERED_CHAINS_BY_ID } from '@constants/chains' - -export const getOrderedChains = ( - connectedChainId: number, - chainId: number, - possibleChains: string[] | undefined -) => { - const filteredChains = ORDERED_CHAINS_BY_ID.filter( - (id) => Number(id) !== connectedChainId && possibleChains?.includes(id) - ) - - let index = filteredChains.findIndex((e) => Number(e) === chainId) - index = index === -1 ? 0 : index - const numberOfChains = filteredChains.length - let newList: number[] = [] - - if (index >= 0 && index < 4) { - newList = filteredChains.slice(0, 6).map((e) => Number(e)) - } else if (numberOfChains - (index + 1) > 1) { - newList = filteredChains.slice(index - 3, index + 3).map((e) => Number(e)) - } else if (numberOfChains - (index + 1) === 1) { - newList = filteredChains.slice(index - 4, index + 2).map((e) => Number(e)) - } else if (numberOfChains - (index + 1) < 1) { - newList = filteredChains.slice(index - 5, index + 1).map((e) => Number(e)) - } - - return newList -} diff --git a/packages/synapse-interface/utils/hooks/useDebounce.ts b/packages/synapse-interface/utils/hooks/useDebounce.ts deleted file mode 100644 index 54c28f1b6d..0000000000 --- a/packages/synapse-interface/utils/hooks/useDebounce.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { useEffect, useState } from 'react' - -// hack fix on https://usehooks.com/useDebounce/ -/** - * @param value - * @param {number} delay in ms - */ -export const useDebounce = (value, delay) => { - const [debouncedValue, setDebouncedValue] = useState(value) - - useEffect(() => { - // Update debounced value after delay - const handler = setTimeout(() => { - setDebouncedValue(value) - }, delay) - - // Cancel the timeout if value changes (also on delay change or unmount) - // This is how we prevent debounced value from updating if value is changed ... - // .. within the delay period. Timeout gets cleared and restarted. - return () => { - clearTimeout(handler) - } - }, [value, delay]) - - return debouncedValue -} diff --git a/packages/synapse-interface/utils/hooks/useDebounce.tsx b/packages/synapse-interface/utils/hooks/useDebounce.tsx deleted file mode 100644 index 864c7c305f..0000000000 --- a/packages/synapse-interface/utils/hooks/useDebounce.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { useEffect, useState } from 'react' - -// hack fix on https://usehooks.com/useDebounce/ -/** - * @param value - * @param {number} delay in ms - */ -export function useDebounce(value, delay) { - const [debouncedValue, setDebouncedValue] = useState(value) - - useEffect(() => { - // Update debounced value after delay - const handler = setTimeout(() => { - setDebouncedValue(value) - }, delay) - - // Cancel the timeout if value changes (also on delay change or unmount) - // This is how we prevent debounced value from updating if value is changed ... - // .. within the delay period. Timeout gets cleared and restarted. - return () => { - clearTimeout(handler) - } - }, [value, delay]) - - return debouncedValue -} diff --git a/packages/synapse-interface/utils/hooks/useSettings.tsx b/packages/synapse-interface/utils/hooks/useSettings.tsx deleted file mode 100644 index f38490d169..0000000000 --- a/packages/synapse-interface/utils/hooks/useSettings.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import createPersistedState from 'use-persisted-state' - -const usePassthroughSettings = createPersistedState('settingsObjStuff') - -export const useSettings = () => { - return usePassthroughSettings({ - expertMode: false, - }) -} diff --git a/packages/synapse-interface/utils/hooks/useTxHistory.ts b/packages/synapse-interface/utils/hooks/useTxHistory.ts deleted file mode 100644 index daf31856a5..0000000000 --- a/packages/synapse-interface/utils/hooks/useTxHistory.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { useState } from 'react' -import _ from 'lodash' - -export const useTxHistory = () => { - // const { account } = useActiveWeb3React() - // const [transactionsByAccount, setTransactionsByAccount] = usePersistedTransactionHistory({}) - - // const transactions = transactionsByAccount[account] ?? [] - - // function setTransactions(txns) { - // setTransactionsByAccount({ - // ...transactionsByAccount, - // [account]: txns - // }) - // } - const [transactions, setTransactions] = useState([]) - - const addTransaction = ({ - transactionHash, - hash, - chainId, - ...transaction - }) => { - const formattedTx = { - transactionHash: transactionHash ?? hash, - chainId, - ...transaction, - } - - const filteredTransactions = transactions.filter( - (tx) => tx.transactionHash !== formattedTx.transactionHash - ) - const arr = [...filteredTransactions, formattedTx] - - setTransactions(arr) - } - - const updateTransactions = (txns) => { - setTransactions((oldTransactions) => { - const newTxnHashes = txns.map((tx) => tx.transactionHash ?? tx.hash) - - const filteredPrevTxns = oldTransactions.filter((tx) => { - const txOverlap = newTxnHashes.includes(tx.transactionHash ?? tx.hash) - return !txOverlap - }) - - const txnsToAdd = _.sortBy( - [ - ...filteredPrevTxns, - ...txns.map((tx) => { - return { ...tx, transactionHash: tx.transactionHash ?? tx.hash } - }), - ], - (tx) => -tx.timestamp - ) - return txnsToAdd - }) - } - - const clear = () => { - setTransactions([]) - } - - return { - transactions, - setTransactions, - addTransaction, - updateTransactions, - clear, - } -} diff --git a/packages/synapse-interface/utils/matchSymbolWithinPool.ts b/packages/synapse-interface/utils/matchSymbolWithinPool.ts deleted file mode 100644 index 974653ab9d..0000000000 --- a/packages/synapse-interface/utils/matchSymbolWithinPool.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { AVWETH } from '@constants/tokens/auxilliary' -import { WETHE, ETH, WETH } from '@constants/tokens/bridgeable' - -/** - * @param {Token} matchCoin the coin in the pool/ token of poolTokens - * @param {Token} compareCoin the coin to compare (fromCoin/toCoin) - */ -export const matchSymbolWithinPool = (matchCoin, compareCoin) => { - let compareSymbol = compareCoin.symbol - if (compareSymbol === WETHE.symbol) { - compareSymbol = AVWETH.symbol - } else if (compareSymbol === ETH.symbol) { - compareSymbol = WETH.symbol - } - return matchCoin.symbol === compareSymbol -} diff --git a/packages/synapse-interface/utils/remove0xPrefix.ts b/packages/synapse-interface/utils/remove0xPrefix.ts deleted file mode 100644 index b5536f0c79..0000000000 --- a/packages/synapse-interface/utils/remove0xPrefix.ts +++ /dev/null @@ -1,9 +0,0 @@ -export const remove0xPrefix = (str?: string): string => { - if (!str) { - return str - } - if (str.startsWith('0x')) { - return str.slice(2) - } - return str -} diff --git a/packages/synapse-interface/utils/toHexStr.ts b/packages/synapse-interface/utils/toHexStr.ts deleted file mode 100644 index 173f6fdebc..0000000000 --- a/packages/synapse-interface/utils/toHexStr.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const toHexStr = (num: number) => { - return `0x${num.toString(16)}` -} diff --git a/packages/synapse-interface/utils/types/index.tsx b/packages/synapse-interface/utils/types/index.tsx index 0e95aa25d5..2ceff00ea1 100644 --- a/packages/synapse-interface/utils/types/index.tsx +++ b/packages/synapse-interface/utils/types/index.tsx @@ -1,6 +1,6 @@ import { BigNumber } from '@ethersproject/bignumber' import * as CHAINS from '@constants/chains/master' -import { getAddress } from '@ethersproject/address' +import { getAddress } from 'viem' export type Chain = { id: number diff --git a/packages/synapse-interface/utils/validateAndParseAddress.ts b/packages/synapse-interface/utils/validateAndParseAddress.ts deleted file mode 100644 index 642b5294ec..0000000000 --- a/packages/synapse-interface/utils/validateAndParseAddress.ts +++ /dev/null @@ -1,13 +0,0 @@ -import warning from 'tiny-warning' -import { getAddress } from '@ethersproject/address' - -export const validateAndParseAddress = (address: string) => { - try { - const checksummedAddress = getAddress(address) - warning(address === checksummedAddress, `${address} is not checksummed.`) - return checksummedAddress - } catch (error) { - console.error(error) - console.error(`${address} is not a valid address.`) - } -} diff --git a/yarn.lock b/yarn.lock index fa3d4ed9c9..46e99cc983 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8689,9 +8689,9 @@ integrity sha512-Qk7fpJ6qFp+26VeQ47WY0mkwXaiq8+76RJcncDEfMc2ocRzXLO67bLFRNI4OX1aGBoPzsM5Y2T+/m1pldOgD+A== "@types/d3-chord@^1.0.9": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-1.0.11.tgz#5760765db1b1a4b936c0d9355a821dde9dd25da2" - integrity sha512-0DdfJ//bxyW3G9Nefwq/LDgazSKNN8NU0lBT3Cza6uVuInC2awMNsAcv1oKyRFLn9z7kXClH5XjwpveZjuz2eg== + version "1.0.14" + resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-1.0.14.tgz#33540343ef45ddbc8f8c48f3b9453426f9a653ae" + integrity sha512-W9rCIbSAhwtmydW5iGg9dwTQIi3SGBOh68/T3ke3PyOgejuSLozmtAMaWNViGaGJCeuM4aFJHTUHQvMedl4ugA== "@types/d3-color@*", "@types/d3-color@3.1.0": version "3.1.0" @@ -8713,6 +8713,13 @@ resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-3.0.1.tgz#194f1317a499edd7e58766f96735bdc0216bb89d" integrity sha512-5KY70ifCCzorkLuIkDe0Z9YTf9RR2CjBX1iaJG+rgM/cPP+sO+q9YdQ9WdhQcgPj1EQiJ2/0+yUkkziTG6Lubg== +"@types/d3-geo@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-3.1.0.tgz#b9e56a079449174f0a2c8684a9a4df3f60522440" + integrity sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ== + dependencies: + "@types/geojson" "*" + "@types/d3-interpolate@3.0.1", "@types/d3-interpolate@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz#e7d17fa4a5830ad56fe22ce3b4fac8541a9572dc" @@ -8726,9 +8733,9 @@ integrity sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg== "@types/d3-path@^1", "@types/d3-path@^1.0.8": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-1.0.9.tgz#73526b150d14cd96e701597cbf346cfd1fd4a58c" - integrity sha512-NaIeSIBiFgSC6IGUBjZWcscUJEq7vpVu7KthHN8eieTV9d9MqkSOZLH4chq1PmcKy06PNe3axLeKmRIyxJ+PZQ== + version "1.0.11" + resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-1.0.11.tgz#45420fee2d93387083b34eae4fe6d996edf482bc" + integrity sha512-4pQMp8ldf7UaB/gR8Fvvy69psNHkTpD/pVw3vmEi8iZAB9EPMBruB1JvHO4BIq9QkUUd2lV1F5YXpMNj7JPBpw== "@types/d3-scale@4.0.2": version "4.0.2" @@ -8745,9 +8752,9 @@ "@types/d3-time" "*" "@types/d3-shape@^1.3.1": - version "1.3.8" - resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-1.3.8.tgz#c3c15ec7436b4ce24e38de517586850f1fea8e89" - integrity sha512-gqfnMz6Fd5H6GOLYixOZP/xlrMtJms9BaS+6oWxTKHNqPGZ93BkWWupQSCYm6YHqx6h9wjRupuJb90bun6ZaYg== + version "1.3.12" + resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-1.3.12.tgz#8f2f9f7a12e631ce6700d6d55b84795ce2c8b259" + integrity sha512-8oMzcd4+poSLGgV0R1Q1rOlx/xdmozS4Xab7np0eamFFUYq71AU9pOCJEFnkXW2aI/oXdVYJzw6pssbSut7Z9Q== dependencies: "@types/d3-path" "^1" @@ -8836,6 +8843,11 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/geojson@*": + version "7946.0.14" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.14.tgz#319b63ad6df705ee2a65a73ef042c8271e696613" + integrity sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg== + "@types/glob@*": version "8.1.0" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-8.1.0.tgz#b63e70155391b0584dce44e7ea25190bbc38f2fc" @@ -9018,11 +9030,16 @@ "@types/level-errors" "*" "@types/node" "*" -"@types/lodash@^4.14.167", "@types/lodash@^4.14.172": +"@types/lodash@^4.14.167": version "4.14.196" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.196.tgz#a7c3d6fc52d8d71328b764e28e080b4169ec7a95" integrity sha512-22y3o88f4a94mKljsZcanlNWPzO0uBsBdzLAngf2tp533LzZcQzb6+eZPJ+vCTt+bqF2XnvT9gejTLsAcJAJyQ== +"@types/lodash@^4.14.172": + version "4.17.0" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.0.tgz#d774355e41f372d5350a4d0714abb48194a489c3" + integrity sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA== + "@types/lru-cache@^5.1.0": version "5.1.1" resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" @@ -9742,17 +9759,17 @@ classnames "^2.3.1" prop-types "^15.6.2" -"@visx/scale@3.3.0": - version "3.3.0" - resolved "https://registry.yarnpkg.com/@visx/scale/-/scale-3.3.0.tgz#552e6ee6f6fda22825e49cf7f091d867f9477c9b" - integrity sha512-H569k7eQEUcFE/X1Zojcb4rUwxurIU4yso21uAuKvXnZcGpDOTr/3YXXHb1JJqOKfLcZtYZWXok6QVDj5ZGtCw== +"@visx/scale@3.5.0": + version "3.5.0" + resolved "https://registry.yarnpkg.com/@visx/scale/-/scale-3.5.0.tgz#c3db3863bbdd24d44781104ef5ee4cdc8df6f11d" + integrity sha512-xo3zrXV2IZxrMq9Y9RUVJUpd93h3NO/r/y3GVi5F9AsbOzOhsLIbsPkunhO9mpUSR8LZ9TiumLEBrY+3frRBSg== dependencies: - "@visx/vendor" "3.3.0" + "@visx/vendor" "3.5.0" "@visx/shape@^3.0.0": - version "3.3.0" - resolved "https://registry.yarnpkg.com/@visx/shape/-/shape-3.3.0.tgz#99c58f64edaa1abcd5912db45a3d13ef5efa3a9f" - integrity sha512-+ojOlcoMnbC16zhwK7HyK4dIB9sUJILQfVNBBNw8TBckCsly+S1WdBKZ+RZvQDppNr2YuiQLsZpr3W9zZJaHtg== + version "3.5.0" + resolved "https://registry.yarnpkg.com/@visx/shape/-/shape-3.5.0.tgz#fa4bb7a9ed863360be541d75c434503246305e36" + integrity sha512-DP3t9jBQ7dSE3e6ptA1xO4QAIGxO55GrY/6P+S6YREuQGjZgq20TLYLAsiaoPEzFSS4tp0m12ZTPivWhU2VBTw== dependencies: "@types/d3-path" "^1.0.8" "@types/d3-shape" "^1.3.1" @@ -9760,22 +9777,23 @@ "@types/react" "*" "@visx/curve" "3.3.0" "@visx/group" "3.3.0" - "@visx/scale" "3.3.0" + "@visx/scale" "3.5.0" classnames "^2.3.1" d3-path "^1.0.5" d3-shape "^1.2.0" lodash "^4.17.21" prop-types "^15.5.10" -"@visx/vendor@3.3.0": - version "3.3.0" - resolved "https://registry.yarnpkg.com/@visx/vendor/-/vendor-3.3.0.tgz#147d2b5e7b9af09be7f00afdde04d6b0e7d32c03" - integrity sha512-Xf4ziUWP3oUN/91ROYgJr2JJ6tET+j4jgVfa0Mj9XFpFJeY7U8aEwrNDM2mbR1draktCFNyy/OQAaFa69pr8qQ== +"@visx/vendor@3.5.0": + version "3.5.0" + resolved "https://registry.yarnpkg.com/@visx/vendor/-/vendor-3.5.0.tgz#a9990382ba759b9c4049be303d65d2cb3ca034a8" + integrity sha512-yt3SEZRVmt36+APsCISSO9eSOtzQkBjt+QRxNRzcTWuzwMAaF3PHCCSe31++kkpgY9yFoF+Gfes1TBe5NlETiQ== dependencies: "@types/d3-array" "3.0.3" "@types/d3-color" "3.1.0" "@types/d3-delaunay" "6.0.1" "@types/d3-format" "3.0.1" + "@types/d3-geo" "3.1.0" "@types/d3-interpolate" "3.0.1" "@types/d3-scale" "4.0.2" "@types/d3-time" "3.0.0" @@ -9784,6 +9802,7 @@ d3-color "3.1.0" d3-delaunay "6.0.2" d3-format "3.1.0" + d3-geo "3.1.0" d3-interpolate "3.0.1" d3-scale "4.0.2" d3-time "3.1.0" @@ -10796,11 +10815,6 @@ add-stream@^1.0.0: resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" integrity sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ== -add@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/add/-/add-2.0.6.tgz#248f0a9f6e5a528ef2295dbeec30532130ae2235" - integrity sha512-j5QzrmsokwWWp6kUcJQySpbG+xfOBqqKnup3OIk1pz+kB/80SLorZ9V8zHFLO92Lcd+hbvq8bT+zOGoPkmBV0Q== - address@^1.0.1, address@^1.1.2: version "1.2.2" resolved "https://registry.yarnpkg.com/address/-/address-1.2.2.tgz#2b5248dac5485a6390532c6a517fda2e3faac89e" @@ -11606,7 +11620,7 @@ auto-bind@~4.0.0: resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-4.0.0.tgz#e3589fc6c2da8f7ca43ba9f84fa52a744fc997fb" integrity sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ== -autoprefixer@^10.4.12, autoprefixer@^10.4.13, autoprefixer@^10.4.7: +autoprefixer@^10.4.12, autoprefixer@^10.4.7: version "10.4.14" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.14.tgz#e28d49902f8e759dd25b153264e862df2705f79d" integrity sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ== @@ -13252,11 +13266,16 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@^2.2.5, classnames@^2.3.1: +classnames@^2.2.5: version "2.3.2" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== +classnames@^2.3.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" + integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== + clean-css@^4.2.3: version "4.2.4" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.4.tgz#733bf46eba4e607c6891ea57c24a989356831178" @@ -14551,7 +14570,7 @@ d3-array@1: resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f" integrity sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw== -"d3-array@2 - 3", "d3-array@2.10.0 - 3", d3-array@^3.1.6: +"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@^3.1.6: version "3.2.4" resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5" integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== @@ -14595,6 +14614,13 @@ d3-ease@^3.0.1: resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== +d3-geo@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.1.0.tgz#74fd54e1f4cebd5185ac2039217a98d39b0a4c0e" + integrity sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA== + dependencies: + d3-array "2.5.0 - 3" + "d3-interpolate@1.2.0 - 3", d3-interpolate@3.0.1, d3-interpolate@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" @@ -15053,11 +15079,11 @@ del@^6.1.1: slash "^3.0.0" delaunator@5: - version "5.0.0" - resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.0.tgz#60f052b28bd91c9b4566850ebf7756efe821d81b" - integrity sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw== + version "5.0.1" + resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.1.tgz#39032b08053923e924d6094fe2cde1a99cc51278" + integrity sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw== dependencies: - robust-predicates "^3.0.0" + robust-predicates "^3.0.2" delay@^5.0.0: version "5.0.0" @@ -18816,7 +18842,7 @@ graphql-request@^4.0.0: extract-files "^9.0.0" form-data "^3.0.0" -graphql-request@^6.0.0, graphql-request@^6.1.0: +graphql-request@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-6.1.0.tgz#f4eb2107967af3c7a5907eb3131c671eac89be4f" integrity sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw== @@ -28231,7 +28257,7 @@ rlp@^2.2.3, rlp@^2.2.4: dependencies: bn.js "^5.2.0" -robust-predicates@^3.0.0: +robust-predicates@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.2.tgz#d5b28528c4824d20fc48df1928d41d9efa1ad771" integrity sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg== @@ -32018,11 +32044,6 @@ use-sync-external-store@1.2.0, use-sync-external-store@^1.0.0, use-sync-external resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== -use-window-focus@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/use-window-focus/-/use-window-focus-1.4.2.tgz#18cd99d14b9f75b7b1d08ea6e1832762731f5510" - integrity sha512-6aLzUtgcph92IoT+ZmEPpkdLW3O5frL7sNIpbt/2pBh6HwHZTRagsIxILrLTfrguzEDQqy5FM76K4wqIj4V6mw== - use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" From dfe844ea965f3c4eafb0b9584e7b82944fad37dd Mon Sep 17 00:00:00 2001 From: abtestingalpha Date: Thu, 14 Mar 2024 15:05:14 +0000 Subject: [PATCH 20/29] Publish - @synapsecns/synapse-interface@0.9.4 --- packages/synapse-interface/CHANGELOG.md | 11 +++++++++++ packages/synapse-interface/package.json | 12 ++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/packages/synapse-interface/CHANGELOG.md b/packages/synapse-interface/CHANGELOG.md index 20390d211c..27c89e01d1 100644 --- a/packages/synapse-interface/CHANGELOG.md +++ b/packages/synapse-interface/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.9.4](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.9.3...@synapsecns/synapse-interface@0.9.4) (2024-03-14) + + +### Bug Fixes + +* **synapse-interface:** deprecate unused dependencies ([#2287](https://github.com/synapsecns/sanguine/issues/2287)) ([e14071b](https://github.com/synapsecns/sanguine/commit/e14071bf1014050036b5e2e0858aa1e84aad2e18)) + + + + + ## [0.9.3](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.9.2...@synapsecns/synapse-interface@0.9.3) (2024-03-14) **Note:** Version bump only for package @synapsecns/synapse-interface diff --git a/packages/synapse-interface/package.json b/packages/synapse-interface/package.json index d2ac24f430..f8f8e15255 100644 --- a/packages/synapse-interface/package.json +++ b/packages/synapse-interface/package.json @@ -1,6 +1,6 @@ { "name": "@synapsecns/synapse-interface", - "version": "0.9.3", + "version": "0.9.4", "private": true, "engines": { "node": ">=16.0.0" @@ -96,19 +96,19 @@ "license": "ISC", "keywords": [], "devDependencies": { - "cypress": "^13.0.0", - "dayjs": "^1.11.7", "@depay/web3-mock": "^14.0.0", - "@testing-library/cypress": "^9.0.0", - "start-server-and-test": "^2.0.0", "@graphql-codegen/cli": "5.0.0", "@graphql-codegen/client-preset": "4.1.0", "@graphql-codegen/introspection": "4.0.0", "@graphql-codegen/typescript-rtk-query": "^2.4.1", + "@testing-library/cypress": "^9.0.0", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^14.0.0", "@types/redux-persist": "^4.3.1", + "cypress": "^13.0.0", + "dayjs": "^1.11.7", "jest": "^29.6.1", - "jest-environment-jsdom": "^29.6.1" + "jest-environment-jsdom": "^29.6.1", + "start-server-and-test": "^2.0.0" } } From 98f48b165f45b2a9b8f291e3020872029ae20abb Mon Sep 17 00:00:00 2001 From: abtestingalpha <104046418+abtestingalpha@users.noreply.github.com> Date: Thu, 14 Mar 2024 11:26:52 -0500 Subject: [PATCH 21/29] fix(synapse-interface): fixes explorer images (#2292) * Fixes explorer images * removes duplicate svgs --- .../explorer/{arbitrum.svg => arbiscan.svg} | 0 .../assets/explorer/aurora.svg | 3 -- .../assets/explorer/avalanche.svg | 3 -- .../assets/explorer/blast.svg | 4 -- .../assets/explorer/boba.svg | 3 -- .../assets/explorer/bscscan.svg | 7 +-- .../assets/explorer/canto.svg | 3 -- .../assets/explorer/cronos.svg | 3 -- .../assets/explorer/dfk-chain.svg | 3 -- .../assets/explorer/dogecoin.svg | 3 -- .../assets/explorer/fantom.svg | 3 -- .../assets/explorer/ftmscan.svg | 3 ++ .../assets/explorer/harmony.svg | 3 -- .../assets/explorer/klaytn.svg | 3 -- .../assets/explorer/metis.svg | 3 -- .../assets/explorer/moonbeam.svg | 3 -- .../assets/explorer/moonriver.svg | 3 -- .../assets/explorer/optimism.svg | 3 -- .../assets/explorer/polygon.svg | 3 -- .../assets/explorer/snowscan.svg | 4 ++ .../constants/chains/master.tsx | 49 +++++++------------ 21 files changed, 28 insertions(+), 84 deletions(-) rename packages/synapse-interface/assets/explorer/{arbitrum.svg => arbiscan.svg} (100%) delete mode 100644 packages/synapse-interface/assets/explorer/aurora.svg delete mode 100644 packages/synapse-interface/assets/explorer/avalanche.svg delete mode 100644 packages/synapse-interface/assets/explorer/blast.svg delete mode 100644 packages/synapse-interface/assets/explorer/boba.svg delete mode 100644 packages/synapse-interface/assets/explorer/canto.svg delete mode 100644 packages/synapse-interface/assets/explorer/cronos.svg delete mode 100644 packages/synapse-interface/assets/explorer/dfk-chain.svg delete mode 100644 packages/synapse-interface/assets/explorer/dogecoin.svg delete mode 100644 packages/synapse-interface/assets/explorer/fantom.svg create mode 100644 packages/synapse-interface/assets/explorer/ftmscan.svg delete mode 100644 packages/synapse-interface/assets/explorer/harmony.svg delete mode 100644 packages/synapse-interface/assets/explorer/klaytn.svg delete mode 100644 packages/synapse-interface/assets/explorer/metis.svg delete mode 100644 packages/synapse-interface/assets/explorer/moonbeam.svg delete mode 100644 packages/synapse-interface/assets/explorer/moonriver.svg delete mode 100644 packages/synapse-interface/assets/explorer/optimism.svg delete mode 100644 packages/synapse-interface/assets/explorer/polygon.svg create mode 100644 packages/synapse-interface/assets/explorer/snowscan.svg diff --git a/packages/synapse-interface/assets/explorer/arbitrum.svg b/packages/synapse-interface/assets/explorer/arbiscan.svg similarity index 100% rename from packages/synapse-interface/assets/explorer/arbitrum.svg rename to packages/synapse-interface/assets/explorer/arbiscan.svg diff --git a/packages/synapse-interface/assets/explorer/aurora.svg b/packages/synapse-interface/assets/explorer/aurora.svg deleted file mode 100644 index 3ea0ebae01..0000000000 --- a/packages/synapse-interface/assets/explorer/aurora.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/packages/synapse-interface/assets/explorer/avalanche.svg b/packages/synapse-interface/assets/explorer/avalanche.svg deleted file mode 100644 index fc5ca97e5d..0000000000 --- a/packages/synapse-interface/assets/explorer/avalanche.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/packages/synapse-interface/assets/explorer/blast.svg b/packages/synapse-interface/assets/explorer/blast.svg deleted file mode 100644 index 5df8a7f017..0000000000 --- a/packages/synapse-interface/assets/explorer/blast.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/synapse-interface/assets/explorer/boba.svg b/packages/synapse-interface/assets/explorer/boba.svg deleted file mode 100644 index 6b65299d1d..0000000000 --- a/packages/synapse-interface/assets/explorer/boba.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/packages/synapse-interface/assets/explorer/bscscan.svg b/packages/synapse-interface/assets/explorer/bscscan.svg index 9409a9c45c..da6febeaf3 100644 --- a/packages/synapse-interface/assets/explorer/bscscan.svg +++ b/packages/synapse-interface/assets/explorer/bscscan.svg @@ -1,3 +1,4 @@ - - - \ No newline at end of file + + + + diff --git a/packages/synapse-interface/assets/explorer/canto.svg b/packages/synapse-interface/assets/explorer/canto.svg deleted file mode 100644 index bc3c2a5797..0000000000 --- a/packages/synapse-interface/assets/explorer/canto.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/packages/synapse-interface/assets/explorer/cronos.svg b/packages/synapse-interface/assets/explorer/cronos.svg deleted file mode 100644 index e3168f2003..0000000000 --- a/packages/synapse-interface/assets/explorer/cronos.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/packages/synapse-interface/assets/explorer/dfk-chain.svg b/packages/synapse-interface/assets/explorer/dfk-chain.svg deleted file mode 100644 index 6f9c65efe0..0000000000 --- a/packages/synapse-interface/assets/explorer/dfk-chain.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/packages/synapse-interface/assets/explorer/dogecoin.svg b/packages/synapse-interface/assets/explorer/dogecoin.svg deleted file mode 100644 index 25cb7d44b0..0000000000 --- a/packages/synapse-interface/assets/explorer/dogecoin.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/packages/synapse-interface/assets/explorer/fantom.svg b/packages/synapse-interface/assets/explorer/fantom.svg deleted file mode 100644 index cbe18b70dd..0000000000 --- a/packages/synapse-interface/assets/explorer/fantom.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/packages/synapse-interface/assets/explorer/ftmscan.svg b/packages/synapse-interface/assets/explorer/ftmscan.svg new file mode 100644 index 0000000000..499bfea387 --- /dev/null +++ b/packages/synapse-interface/assets/explorer/ftmscan.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/synapse-interface/assets/explorer/harmony.svg b/packages/synapse-interface/assets/explorer/harmony.svg deleted file mode 100644 index a08908db08..0000000000 --- a/packages/synapse-interface/assets/explorer/harmony.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/packages/synapse-interface/assets/explorer/klaytn.svg b/packages/synapse-interface/assets/explorer/klaytn.svg deleted file mode 100644 index 7442140766..0000000000 --- a/packages/synapse-interface/assets/explorer/klaytn.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/packages/synapse-interface/assets/explorer/metis.svg b/packages/synapse-interface/assets/explorer/metis.svg deleted file mode 100644 index a6deadf00d..0000000000 --- a/packages/synapse-interface/assets/explorer/metis.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/packages/synapse-interface/assets/explorer/moonbeam.svg b/packages/synapse-interface/assets/explorer/moonbeam.svg deleted file mode 100644 index 04cfc82fbc..0000000000 --- a/packages/synapse-interface/assets/explorer/moonbeam.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/packages/synapse-interface/assets/explorer/moonriver.svg b/packages/synapse-interface/assets/explorer/moonriver.svg deleted file mode 100644 index 0a6f6ee270..0000000000 --- a/packages/synapse-interface/assets/explorer/moonriver.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/packages/synapse-interface/assets/explorer/optimism.svg b/packages/synapse-interface/assets/explorer/optimism.svg deleted file mode 100644 index b818976a23..0000000000 --- a/packages/synapse-interface/assets/explorer/optimism.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/packages/synapse-interface/assets/explorer/polygon.svg b/packages/synapse-interface/assets/explorer/polygon.svg deleted file mode 100644 index 5ac59821dc..0000000000 --- a/packages/synapse-interface/assets/explorer/polygon.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/packages/synapse-interface/assets/explorer/snowscan.svg b/packages/synapse-interface/assets/explorer/snowscan.svg new file mode 100644 index 0000000000..a20a66a2ff --- /dev/null +++ b/packages/synapse-interface/assets/explorer/snowscan.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/synapse-interface/constants/chains/master.tsx b/packages/synapse-interface/constants/chains/master.tsx index 34bb976247..0f362b646d 100644 --- a/packages/synapse-interface/constants/chains/master.tsx +++ b/packages/synapse-interface/constants/chains/master.tsx @@ -20,25 +20,11 @@ import optimismImg from '@assets/chains/optimism.svg' import polygonImg from '@assets/chains/polygon.svg' import ethExplorerImg from '@assets/explorer/etherscan.svg' -import arbitrumExplorerImg from '@assets/explorer/arbitrum.svg' -import blastExplorerImg from '@assets/explorer/blast.svg' +import arbitrumExplorerImg from '@assets/explorer/arbiscan.svg' import bnbExplorerImg from '@assets/explorer/bscscan.svg' -import avalancheExplorerImg from '@assets/explorer/avalanche.svg' -import cantoExplorerImg from '@assets/explorer/canto.svg' -import optimismExplorerImg from '@assets/explorer/optimism.svg' -import polygonExplorerImg from '@assets/explorer/polygon.svg' -import dfkExplorerImg from '@assets/explorer/dfk-chain.svg' -import klaytynExplorerImg from '@assets/explorer/klaytn.svg' -import fantomExplorerImg from '@assets/explorer/fantom.svg' -import cronosExplorerImg from '@assets/explorer/cronos.svg' -import bobaExplorerImg from '@assets/explorer/boba.svg' -import metisExplorerImg from '@assets/explorer/metis.svg' -import auroraExplorerImg from '@assets/explorer/aurora.svg' -import harmonyExplorerImg from '@assets/explorer/harmony.svg' -import moonbeamExplorerImg from '@assets/explorer/moonbeam.svg' -import moonriverExplorerImg from '@assets/explorer/moonriver.svg' -import dogeExplorerImg from '@assets/explorer/dogecoin.svg' import baseExplorerImg from '@assets/explorer/basescan.svg' +import avalancheExplorerImg from '@assets/explorer/snowscan.svg' +import fantomExplorerImg from '@assets/explorer/ftmscan.svg' import { Chain } from '@types' @@ -145,7 +131,7 @@ export const CANTO: Chain = { nativeCurrency: { name: 'Canto', symbol: 'CANTO', decimals: 18 }, explorerUrl: 'https://tuber.build/', explorerName: 'Canto Explorer', - explorerImg: cantoExplorerImg, + explorerImg: cantoImg, color: 'green', } @@ -166,7 +152,7 @@ export const OPTIMISM: Chain = { nativeCurrency: { name: 'Ethereum', symbol: 'ETH', decimals: 18 }, explorerUrl: 'https://optimistic.etherscan.io', explorerName: 'Optimism Explorer', - explorerImg: optimismExplorerImg, + explorerImg: optimismImg, color: 'red', } @@ -187,7 +173,7 @@ export const POLYGON: Chain = { nativeCurrency: { name: 'Matic', symbol: 'MATIC', decimals: 18 }, explorerUrl: 'https://polygonscan.com', explorerName: 'PolygonScan', - explorerImg: polygonExplorerImg, + explorerImg: polygonImg, color: 'purple', } @@ -207,7 +193,7 @@ export const DFK: Chain = { nativeCurrency: { name: 'Jewel', symbol: 'JEWEL', decimals: 18 }, explorerUrl: 'https://subnets.avax.network/defi-kingdoms', explorerName: 'DFK Subnet Explorer', - explorerImg: dfkExplorerImg, + explorerImg: dfkImg, color: 'lime', } @@ -227,7 +213,7 @@ export const KLAYTN: Chain = { nativeCurrency: { name: 'Klaytn', symbol: 'KLAY', decimals: 18 }, explorerUrl: 'https://scope.klaytn.com', explorerName: 'Klaytn Explorer', - explorerImg: klaytynExplorerImg, + explorerImg: klaytnImg, color: 'orange', } @@ -267,7 +253,7 @@ export const CRONOS: Chain = { nativeCurrency: { name: 'Cronos', symbol: 'CRO', decimals: 18 }, explorerUrl: 'https://cronoscan.com', explorerName: 'CronoScan', - explorerImg: cronosExplorerImg, + explorerImg: cronosImg, color: 'gray', } @@ -287,7 +273,7 @@ export const BOBA: Chain = { nativeCurrency: { name: 'Ethereum', symbol: 'ETH', decimals: 18 }, explorerUrl: 'https://bobascan.com', explorerName: 'Boba Explorer', - explorerImg: bobaExplorerImg, + explorerImg: bobaImg, color: 'lime', } @@ -307,7 +293,7 @@ export const METIS: Chain = { nativeCurrency: { name: 'Metis', symbol: 'METIS', decimals: 18 }, explorerUrl: 'https://andromeda-explorer.metis.io', explorerName: 'Metis Explorer', - explorerImg: metisExplorerImg, + explorerImg: metisImg, color: 'teal', } @@ -327,7 +313,7 @@ export const AURORA: Chain = { nativeCurrency: { name: 'Ethereum', symbol: 'ETH', decimals: 18 }, explorerUrl: 'https://explorer.mainnet.aurora.dev', explorerName: 'Aurora Explorer', - explorerImg: auroraExplorerImg, + explorerImg: auroraImg, color: 'lime', } @@ -347,7 +333,7 @@ export const HARMONY: Chain = { nativeCurrency: { name: 'Harmony One', symbol: 'ONE', decimals: 18 }, explorerUrl: 'https://explorer.harmony.one', explorerName: 'Harmony Explorer', - explorerImg: harmonyExplorerImg, + explorerImg: harmonyImg, color: 'cyan', } @@ -367,7 +353,7 @@ export const MOONBEAM: Chain = { nativeCurrency: { name: 'Glimmer', symbol: 'GLMR', decimals: 18 }, explorerUrl: 'https://moonbeam.moonscan.io', explorerName: 'Moonbeam Explorer', - explorerImg: moonbeamExplorerImg, + explorerImg: moonbeamImg, color: 'teal', } @@ -387,7 +373,7 @@ export const MOONRIVER: Chain = { nativeCurrency: { name: 'Moonriver', symbol: 'MOVR', decimals: 18 }, explorerUrl: 'https://moonriver.moonscan.io', explorerName: 'Moonriver Explorer', - explorerImg: moonriverExplorerImg, + explorerImg: moonriverImg, color: 'purple', } @@ -407,7 +393,7 @@ export const DOGE: Chain = { nativeCurrency: { name: 'DOGE', symbol: 'DOGE', decimals: 18 }, explorerUrl: 'https://explorer.dogechain.dog', explorerName: 'Dogechain Explorer', - explorerImg: dogeExplorerImg, + explorerImg: dogechainImg, color: 'purple', } @@ -436,7 +422,6 @@ export const BASE: Chain = { color: 'blue', } -// TODO: UPDATE ALL PARAMETERS FOR MAINNET export const BLAST: Chain = { priorityRank: 90, id: 81457, @@ -452,7 +437,7 @@ export const BLAST: Chain = { }, explorerUrl: 'https://blastscan.io', explorerName: 'Blastscan', - explorerImg: blastExplorerImg, + explorerImg: blastImg, blockTime: 3000, nativeCurrency: { name: 'Ether', From 5c3dc590b70550b48a2016996ad749593a712cb4 Mon Sep 17 00:00:00 2001 From: abtestingalpha Date: Thu, 14 Mar 2024 16:30:24 +0000 Subject: [PATCH 22/29] Publish - @synapsecns/synapse-interface@0.9.5 --- packages/synapse-interface/CHANGELOG.md | 11 +++++++++++ packages/synapse-interface/package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/synapse-interface/CHANGELOG.md b/packages/synapse-interface/CHANGELOG.md index 27c89e01d1..11a2cb803c 100644 --- a/packages/synapse-interface/CHANGELOG.md +++ b/packages/synapse-interface/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.9.5](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.9.4...@synapsecns/synapse-interface@0.9.5) (2024-03-14) + + +### Bug Fixes + +* **synapse-interface:** fixes explorer images ([#2292](https://github.com/synapsecns/sanguine/issues/2292)) ([98f48b1](https://github.com/synapsecns/sanguine/commit/98f48b165f45b2a9b8f291e3020872029ae20abb)) + + + + + ## [0.9.4](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.9.3...@synapsecns/synapse-interface@0.9.4) (2024-03-14) diff --git a/packages/synapse-interface/package.json b/packages/synapse-interface/package.json index f8f8e15255..d29e0634d8 100644 --- a/packages/synapse-interface/package.json +++ b/packages/synapse-interface/package.json @@ -1,6 +1,6 @@ { "name": "@synapsecns/synapse-interface", - "version": "0.9.4", + "version": "0.9.5", "private": true, "engines": { "node": ">=16.0.0" From a4c9bf1dbba0266448f7ad5a5b91bb4280f83e76 Mon Sep 17 00:00:00 2001 From: lawsonkight Date: Thu, 14 Mar 2024 11:35:56 -0700 Subject: [PATCH 23/29] compress background image file (#2297) --- .../synapse-interface/public/landingBg.svg | 10247 +--------------- 1 file changed, 1 insertion(+), 10246 deletions(-) diff --git a/packages/synapse-interface/public/landingBg.svg b/packages/synapse-interface/public/landingBg.svg index 3012143b16..36bd972ac1 100644 --- a/packages/synapse-interface/public/landingBg.svg +++ b/packages/synapse-interface/public/landingBg.svg @@ -1,10246 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file From ac4882981a20f877676110011f42c3de0c579897 Mon Sep 17 00:00:00 2001 From: abtestingalpha <104046418+abtestingalpha@users.noreply.github.com> Date: Thu, 14 Mar 2024 13:37:07 -0500 Subject: [PATCH 24/29] Update for removed pool (#2296) --- packages/synapse-interface/constants/bridgeMap.ts | 9 +-------- packages/widget/src/constants/bridgeMap.ts | 9 +-------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/packages/synapse-interface/constants/bridgeMap.ts b/packages/synapse-interface/constants/bridgeMap.ts index c40a689fd7..f229b4633a 100644 --- a/packages/synapse-interface/constants/bridgeMap.ts +++ b/packages/synapse-interface/constants/bridgeMap.ts @@ -1025,7 +1025,7 @@ export const BRIDGE_MAP = { symbol: 'nETH', origin: ['nETH'], destination: ['nETH'], - swappable: ['0x5FD55A1B9FC24967C4dB09C513C3BA0DFa7FF687'], + swappable: [], }, '0x4e71A2E537B7f9D9413D3991D37958c0b5e1e503': { decimals: 18, @@ -1045,13 +1045,6 @@ export const BRIDGE_MAP = { destination: ['SYN'], swappable: [], }, - '0x5FD55A1B9FC24967C4dB09C513C3BA0DFa7FF687': { - decimals: 18, - symbol: 'ETH', - origin: ['nETH'], - destination: ['nETH'], - swappable: ['0x09fEC30669d63A13c666d2129230dD5588E2e240'], - }, '0x80b5a32E4F032B2a058b4F29EC95EEfEEB87aDcd': { decimals: 6, symbol: 'USDC', diff --git a/packages/widget/src/constants/bridgeMap.ts b/packages/widget/src/constants/bridgeMap.ts index c40a689fd7..f229b4633a 100644 --- a/packages/widget/src/constants/bridgeMap.ts +++ b/packages/widget/src/constants/bridgeMap.ts @@ -1025,7 +1025,7 @@ export const BRIDGE_MAP = { symbol: 'nETH', origin: ['nETH'], destination: ['nETH'], - swappable: ['0x5FD55A1B9FC24967C4dB09C513C3BA0DFa7FF687'], + swappable: [], }, '0x4e71A2E537B7f9D9413D3991D37958c0b5e1e503': { decimals: 18, @@ -1045,13 +1045,6 @@ export const BRIDGE_MAP = { destination: ['SYN'], swappable: [], }, - '0x5FD55A1B9FC24967C4dB09C513C3BA0DFa7FF687': { - decimals: 18, - symbol: 'ETH', - origin: ['nETH'], - destination: ['nETH'], - swappable: ['0x09fEC30669d63A13c666d2129230dD5588E2e240'], - }, '0x80b5a32E4F032B2a058b4F29EC95EEfEEB87aDcd': { decimals: 6, symbol: 'USDC', From 9354237920dae97100c3311dcdab241eada032c5 Mon Sep 17 00:00:00 2001 From: abtestingalpha Date: Thu, 14 Mar 2024 18:40:56 +0000 Subject: [PATCH 25/29] Publish - @synapsecns/synapse-interface@0.9.6 - @synapsecns/widget@0.1.5 --- packages/synapse-interface/CHANGELOG.md | 8 ++++++++ packages/synapse-interface/package.json | 2 +- packages/widget/CHANGELOG.md | 8 ++++++++ packages/widget/package.json | 2 +- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/synapse-interface/CHANGELOG.md b/packages/synapse-interface/CHANGELOG.md index 11a2cb803c..51821779a5 100644 --- a/packages/synapse-interface/CHANGELOG.md +++ b/packages/synapse-interface/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.9.6](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.9.5...@synapsecns/synapse-interface@0.9.6) (2024-03-14) + +**Note:** Version bump only for package @synapsecns/synapse-interface + + + + + ## [0.9.5](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.9.4...@synapsecns/synapse-interface@0.9.5) (2024-03-14) diff --git a/packages/synapse-interface/package.json b/packages/synapse-interface/package.json index d29e0634d8..ca691b955c 100644 --- a/packages/synapse-interface/package.json +++ b/packages/synapse-interface/package.json @@ -1,6 +1,6 @@ { "name": "@synapsecns/synapse-interface", - "version": "0.9.5", + "version": "0.9.6", "private": true, "engines": { "node": ">=16.0.0" diff --git a/packages/widget/CHANGELOG.md b/packages/widget/CHANGELOG.md index 806ce3fc98..0289845f85 100644 --- a/packages/widget/CHANGELOG.md +++ b/packages/widget/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.5](https://github.com/synapsecns/sanguine/compare/@synapsecns/widget@0.1.4...@synapsecns/widget@0.1.5) (2024-03-14) + +**Note:** Version bump only for package @synapsecns/widget + + + + + ## [0.1.4](https://github.com/synapsecns/sanguine/compare/@synapsecns/widget@0.1.3...@synapsecns/widget@0.1.4) (2024-03-14) **Note:** Version bump only for package @synapsecns/widget diff --git a/packages/widget/package.json b/packages/widget/package.json index 8c2143362f..f7b7b5cc4a 100644 --- a/packages/widget/package.json +++ b/packages/widget/package.json @@ -1,7 +1,7 @@ { "name": "@synapsecns/widget", "description": "Widget library for interacting with the Synapse Protocol", - "version": "0.1.4", + "version": "0.1.5", "license": "MIT", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", From 7de5e30c18ec4c7d05138c34419e7057234bc965 Mon Sep 17 00:00:00 2001 From: lawsonkight Date: Thu, 14 Mar 2024 12:11:38 -0700 Subject: [PATCH 26/29] move compressed images from constants package to synapse-interface (#2298) --- .../assets/chains/arbitrum.svg | 9 +- .../assets/chains/aurora.svg | 11 +- .../assets/chains/avalanche.svg | 5 +- .../synapse-interface/assets/chains/base.svg | 11 +- .../synapse-interface/assets/chains/bnb.svg | 4 +- .../synapse-interface/assets/chains/boba.svg | 12 +- .../synapse-interface/assets/chains/canto.svg | 4 +- .../assets/chains/cronos.svg | 6 +- .../synapse-interface/assets/chains/dfk.svg | 17 +-- .../assets/chains/dogechain.svg | 10 +- .../assets/chains/ethereum.svg | 10 +- .../assets/chains/fantom.svg | 5 +- .../assets/chains/harmony.svg | 11 +- .../assets/chains/klaytn.svg | 31 +---- .../synapse-interface/assets/chains/metis.svg | 4 +- .../assets/chains/moonbeam.svg | 18 +-- .../assets/chains/moonriver.svg | 20 +--- .../assets/chains/optimism.svg | 6 +- .../assets/chains/polygon.svg | 11 +- .../synapse-interface/assets/icons/ageur.svg | 12 +- .../synapse-interface/assets/icons/avax.svg | 5 +- .../synapse-interface/assets/icons/avweth.svg | 23 +--- .../synapse-interface/assets/icons/btc.svg | 12 +- .../synapse-interface/assets/icons/busd.svg | 8 +- .../synapse-interface/assets/icons/crvusd.svg | 104 +---------------- .../synapse-interface/assets/icons/dai.svg | 5 +- .../synapse-interface/assets/icons/dog.svg | 15 +-- .../synapse-interface/assets/icons/eth.svg | 18 +-- .../synapse-interface/assets/icons/frax.svg | 6 +- .../synapse-interface/assets/icons/ftm.svg | 5 +- .../synapse-interface/assets/icons/fusdt.svg | 26 +---- .../synapse-interface/assets/icons/gmx.svg | 16 +-- .../synapse-interface/assets/icons/gohm.svg | 22 +--- .../synapse-interface/assets/icons/h2o.svg | 16 +-- .../assets/icons/highstreet.svg | 12 +- .../assets/icons/hyperjump.svg | 15 +-- .../synapse-interface/assets/icons/jewel.svg | 15 +-- .../synapse-interface/assets/icons/klay.svg | 31 +---- .../synapse-interface/assets/icons/l2dao.svg | 48 +------- .../synapse-interface/assets/icons/link.svg | 11 +- .../synapse-interface/assets/icons/matic.svg | 11 +- .../assets/icons/metamask.svg | 2 +- .../synapse-interface/assets/icons/mim.svg | 2 +- .../synapse-interface/assets/icons/movr.svg | 20 +--- .../synapse-interface/assets/icons/neth.svg | 23 +--- .../synapse-interface/assets/icons/newo.svg | 107 +----------------- .../synapse-interface/assets/icons/nfd.svg | 15 +-- .../synapse-interface/assets/icons/note.svg | 20 +--- .../synapse-interface/assets/icons/nusd.svg | 17 +-- .../synapse-interface/assets/icons/op.svg | 6 +- .../synapse-interface/assets/icons/pepe.svg | 15 +-- .../synapse-interface/assets/icons/pls.svg | 91 +-------------- .../synapse-interface/assets/icons/sdt.svg | 14 +-- .../synapse-interface/assets/icons/sfi.svg | 5 +- .../synapse-interface/assets/icons/solar.svg | 45 +------- .../synapse-interface/assets/icons/susd.svg | 2 +- .../synapse-interface/assets/icons/sushi.svg | 2 +- .../synapse-interface/assets/icons/syn.svg | 51 +-------- .../synapse-interface/assets/icons/unidex.svg | 16 +-- .../synapse-interface/assets/icons/usdc.svg | 13 +-- .../synapse-interface/assets/icons/usdt.svg | 5 +- .../synapse-interface/assets/icons/vsta.svg | 27 +---- .../synapse-interface/assets/icons/wbtc.svg | 10 +- .../synapse-interface/assets/icons/weth.svg | 18 +-- 64 files changed, 64 insertions(+), 1103 deletions(-) diff --git a/packages/synapse-interface/assets/chains/arbitrum.svg b/packages/synapse-interface/assets/chains/arbitrum.svg index f098c0d248..cb285a937a 100644 --- a/packages/synapse-interface/assets/chains/arbitrum.svg +++ b/packages/synapse-interface/assets/chains/arbitrum.svg @@ -1,8 +1 @@ - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/chains/aurora.svg b/packages/synapse-interface/assets/chains/aurora.svg index f3a1875f12..5b5441b3dd 100644 --- a/packages/synapse-interface/assets/chains/aurora.svg +++ b/packages/synapse-interface/assets/chains/aurora.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/chains/avalanche.svg b/packages/synapse-interface/assets/chains/avalanche.svg index ab95c44cab..5695785b66 100644 --- a/packages/synapse-interface/assets/chains/avalanche.svg +++ b/packages/synapse-interface/assets/chains/avalanche.svg @@ -1,4 +1 @@ - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/chains/base.svg b/packages/synapse-interface/assets/chains/base.svg index 75100d4bd2..5dd1e67af0 100644 --- a/packages/synapse-interface/assets/chains/base.svg +++ b/packages/synapse-interface/assets/chains/base.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/chains/bnb.svg b/packages/synapse-interface/assets/chains/bnb.svg index 3af90289df..4279646a3d 100644 --- a/packages/synapse-interface/assets/chains/bnb.svg +++ b/packages/synapse-interface/assets/chains/bnb.svg @@ -1,3 +1 @@ - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/chains/boba.svg b/packages/synapse-interface/assets/chains/boba.svg index a1177ea681..6f3f19fdfa 100644 --- a/packages/synapse-interface/assets/chains/boba.svg +++ b/packages/synapse-interface/assets/chains/boba.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/chains/canto.svg b/packages/synapse-interface/assets/chains/canto.svg index 9312b7c0cf..20e0fe2177 100644 --- a/packages/synapse-interface/assets/chains/canto.svg +++ b/packages/synapse-interface/assets/chains/canto.svg @@ -1,3 +1 @@ - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/chains/cronos.svg b/packages/synapse-interface/assets/chains/cronos.svg index 289246bb8b..f2c429fc7f 100644 --- a/packages/synapse-interface/assets/chains/cronos.svg +++ b/packages/synapse-interface/assets/chains/cronos.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/chains/dfk.svg b/packages/synapse-interface/assets/chains/dfk.svg index ccc5869eb9..7daf4cc71e 100644 --- a/packages/synapse-interface/assets/chains/dfk.svg +++ b/packages/synapse-interface/assets/chains/dfk.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/chains/dogechain.svg b/packages/synapse-interface/assets/chains/dogechain.svg index 29058988eb..9c8a52c0cb 100644 --- a/packages/synapse-interface/assets/chains/dogechain.svg +++ b/packages/synapse-interface/assets/chains/dogechain.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/chains/ethereum.svg b/packages/synapse-interface/assets/chains/ethereum.svg index 0b13331176..407dcd3072 100644 --- a/packages/synapse-interface/assets/chains/ethereum.svg +++ b/packages/synapse-interface/assets/chains/ethereum.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/chains/fantom.svg b/packages/synapse-interface/assets/chains/fantom.svg index 47788393d7..3e23ff5c0e 100644 --- a/packages/synapse-interface/assets/chains/fantom.svg +++ b/packages/synapse-interface/assets/chains/fantom.svg @@ -1,4 +1 @@ - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/chains/harmony.svg b/packages/synapse-interface/assets/chains/harmony.svg index 1ed4fa47b6..4ce9dc2a07 100644 --- a/packages/synapse-interface/assets/chains/harmony.svg +++ b/packages/synapse-interface/assets/chains/harmony.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/chains/klaytn.svg b/packages/synapse-interface/assets/chains/klaytn.svg index 91a75d69f2..88efdb79b5 100644 --- a/packages/synapse-interface/assets/chains/klaytn.svg +++ b/packages/synapse-interface/assets/chains/klaytn.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/chains/metis.svg b/packages/synapse-interface/assets/chains/metis.svg index a6deadf00d..fd1342a2c0 100644 --- a/packages/synapse-interface/assets/chains/metis.svg +++ b/packages/synapse-interface/assets/chains/metis.svg @@ -1,3 +1 @@ - - - \ No newline at end of file + \ No newline at end of file diff --git a/packages/synapse-interface/assets/chains/moonbeam.svg b/packages/synapse-interface/assets/chains/moonbeam.svg index dc4a6cb7a1..0cbeda36a7 100644 --- a/packages/synapse-interface/assets/chains/moonbeam.svg +++ b/packages/synapse-interface/assets/chains/moonbeam.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/chains/moonriver.svg b/packages/synapse-interface/assets/chains/moonriver.svg index b9c79fc2e1..07cf4ddfcd 100644 --- a/packages/synapse-interface/assets/chains/moonriver.svg +++ b/packages/synapse-interface/assets/chains/moonriver.svg @@ -1,19 +1 @@ - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/chains/optimism.svg b/packages/synapse-interface/assets/chains/optimism.svg index 731740a446..7378f33b2b 100644 --- a/packages/synapse-interface/assets/chains/optimism.svg +++ b/packages/synapse-interface/assets/chains/optimism.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/chains/polygon.svg b/packages/synapse-interface/assets/chains/polygon.svg index bd44d1a402..879ae5a82c 100644 --- a/packages/synapse-interface/assets/chains/polygon.svg +++ b/packages/synapse-interface/assets/chains/polygon.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/ageur.svg b/packages/synapse-interface/assets/icons/ageur.svg index c5116082ff..e48ff825bc 100644 --- a/packages/synapse-interface/assets/icons/ageur.svg +++ b/packages/synapse-interface/assets/icons/ageur.svg @@ -1,11 +1 @@ - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/avax.svg b/packages/synapse-interface/assets/icons/avax.svg index ab95c44cab..5695785b66 100644 --- a/packages/synapse-interface/assets/icons/avax.svg +++ b/packages/synapse-interface/assets/icons/avax.svg @@ -1,4 +1 @@ - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/avweth.svg b/packages/synapse-interface/assets/icons/avweth.svg index a34de53076..8e9d055972 100644 --- a/packages/synapse-interface/assets/icons/avweth.svg +++ b/packages/synapse-interface/assets/icons/avweth.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/btc.svg b/packages/synapse-interface/assets/icons/btc.svg index 08243771aa..a10e2bcc2c 100644 --- a/packages/synapse-interface/assets/icons/btc.svg +++ b/packages/synapse-interface/assets/icons/btc.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/busd.svg b/packages/synapse-interface/assets/icons/busd.svg index 86b599151a..939021a69d 100644 --- a/packages/synapse-interface/assets/icons/busd.svg +++ b/packages/synapse-interface/assets/icons/busd.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/crvusd.svg b/packages/synapse-interface/assets/icons/crvusd.svg index ba287ce36c..de40a549fc 100644 --- a/packages/synapse-interface/assets/icons/crvusd.svg +++ b/packages/synapse-interface/assets/icons/crvusd.svg @@ -1,103 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/dai.svg b/packages/synapse-interface/assets/icons/dai.svg index aa054bc7ef..41d6d21513 100644 --- a/packages/synapse-interface/assets/icons/dai.svg +++ b/packages/synapse-interface/assets/icons/dai.svg @@ -1,4 +1 @@ - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/dog.svg b/packages/synapse-interface/assets/icons/dog.svg index 5974c3c474..1d7640718a 100644 --- a/packages/synapse-interface/assets/icons/dog.svg +++ b/packages/synapse-interface/assets/icons/dog.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/eth.svg b/packages/synapse-interface/assets/icons/eth.svg index 99d1e3ef08..e9dcc7f0c3 100644 --- a/packages/synapse-interface/assets/icons/eth.svg +++ b/packages/synapse-interface/assets/icons/eth.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/frax.svg b/packages/synapse-interface/assets/icons/frax.svg index 7dac7ad9d4..cf8c89f20d 100644 --- a/packages/synapse-interface/assets/icons/frax.svg +++ b/packages/synapse-interface/assets/icons/frax.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/ftm.svg b/packages/synapse-interface/assets/icons/ftm.svg index c0ee1877b6..81b17f14c6 100644 --- a/packages/synapse-interface/assets/icons/ftm.svg +++ b/packages/synapse-interface/assets/icons/ftm.svg @@ -1,4 +1 @@ - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/fusdt.svg b/packages/synapse-interface/assets/icons/fusdt.svg index 38005cadd9..5d813d5824 100644 --- a/packages/synapse-interface/assets/icons/fusdt.svg +++ b/packages/synapse-interface/assets/icons/fusdt.svg @@ -1,25 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/gmx.svg b/packages/synapse-interface/assets/icons/gmx.svg index d76d010222..c1534ad171 100644 --- a/packages/synapse-interface/assets/icons/gmx.svg +++ b/packages/synapse-interface/assets/icons/gmx.svg @@ -1,15 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/gohm.svg b/packages/synapse-interface/assets/icons/gohm.svg index c719c8685e..7e4842d855 100644 --- a/packages/synapse-interface/assets/icons/gohm.svg +++ b/packages/synapse-interface/assets/icons/gohm.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/h2o.svg b/packages/synapse-interface/assets/icons/h2o.svg index 4b72fb689e..a2935082de 100644 --- a/packages/synapse-interface/assets/icons/h2o.svg +++ b/packages/synapse-interface/assets/icons/h2o.svg @@ -1,15 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/highstreet.svg b/packages/synapse-interface/assets/icons/highstreet.svg index 37e63d0782..eb53b0ea3e 100644 --- a/packages/synapse-interface/assets/icons/highstreet.svg +++ b/packages/synapse-interface/assets/icons/highstreet.svg @@ -1,11 +1 @@ - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/hyperjump.svg b/packages/synapse-interface/assets/icons/hyperjump.svg index 09635e9432..5f8ca538f5 100644 --- a/packages/synapse-interface/assets/icons/hyperjump.svg +++ b/packages/synapse-interface/assets/icons/hyperjump.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/jewel.svg b/packages/synapse-interface/assets/icons/jewel.svg index ddb6309c7e..7b6cd90f18 100644 --- a/packages/synapse-interface/assets/icons/jewel.svg +++ b/packages/synapse-interface/assets/icons/jewel.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/klay.svg b/packages/synapse-interface/assets/icons/klay.svg index 91a75d69f2..552e0a6e50 100644 --- a/packages/synapse-interface/assets/icons/klay.svg +++ b/packages/synapse-interface/assets/icons/klay.svg @@ -1,30 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/packages/synapse-interface/assets/icons/l2dao.svg b/packages/synapse-interface/assets/icons/l2dao.svg index b6f532c8f5..22175d2cb7 100644 --- a/packages/synapse-interface/assets/icons/l2dao.svg +++ b/packages/synapse-interface/assets/icons/l2dao.svg @@ -1,47 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/link.svg b/packages/synapse-interface/assets/icons/link.svg index c4b8f61c01..cc848c331c 100644 --- a/packages/synapse-interface/assets/icons/link.svg +++ b/packages/synapse-interface/assets/icons/link.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/matic.svg b/packages/synapse-interface/assets/icons/matic.svg index c4eee4dc83..879ae5a82c 100644 --- a/packages/synapse-interface/assets/icons/matic.svg +++ b/packages/synapse-interface/assets/icons/matic.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/metamask.svg b/packages/synapse-interface/assets/icons/metamask.svg index 65b3f54416..fa6d5b322b 100644 --- a/packages/synapse-interface/assets/icons/metamask.svg +++ b/packages/synapse-interface/assets/icons/metamask.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/mim.svg b/packages/synapse-interface/assets/icons/mim.svg index 4ae938c2ff..6397e92bae 100644 --- a/packages/synapse-interface/assets/icons/mim.svg +++ b/packages/synapse-interface/assets/icons/mim.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/movr.svg b/packages/synapse-interface/assets/icons/movr.svg index 9d5d25bf0b..07cf4ddfcd 100644 --- a/packages/synapse-interface/assets/icons/movr.svg +++ b/packages/synapse-interface/assets/icons/movr.svg @@ -1,19 +1 @@ - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/neth.svg b/packages/synapse-interface/assets/icons/neth.svg index 8357f4993e..913868f284 100644 --- a/packages/synapse-interface/assets/icons/neth.svg +++ b/packages/synapse-interface/assets/icons/neth.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/newo.svg b/packages/synapse-interface/assets/icons/newo.svg index e72e30525f..444ed2965f 100644 --- a/packages/synapse-interface/assets/icons/newo.svg +++ b/packages/synapse-interface/assets/icons/newo.svg @@ -1,106 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/nfd.svg b/packages/synapse-interface/assets/icons/nfd.svg index ccee410cb8..7534a91235 100644 --- a/packages/synapse-interface/assets/icons/nfd.svg +++ b/packages/synapse-interface/assets/icons/nfd.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/note.svg b/packages/synapse-interface/assets/icons/note.svg index 47f845abd6..c1be5c5dc9 100644 --- a/packages/synapse-interface/assets/icons/note.svg +++ b/packages/synapse-interface/assets/icons/note.svg @@ -1,19 +1 @@ - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/nusd.svg b/packages/synapse-interface/assets/icons/nusd.svg index bff0657146..191a497c9e 100644 --- a/packages/synapse-interface/assets/icons/nusd.svg +++ b/packages/synapse-interface/assets/icons/nusd.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/op.svg b/packages/synapse-interface/assets/icons/op.svg index fdc2a70956..bb5f2a1511 100644 --- a/packages/synapse-interface/assets/icons/op.svg +++ b/packages/synapse-interface/assets/icons/op.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/pepe.svg b/packages/synapse-interface/assets/icons/pepe.svg index 48f3478f53..f08be7d1d6 100644 --- a/packages/synapse-interface/assets/icons/pepe.svg +++ b/packages/synapse-interface/assets/icons/pepe.svg @@ -1,14 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/pls.svg b/packages/synapse-interface/assets/icons/pls.svg index 245aaaa6a1..fccdbcd2ca 100644 --- a/packages/synapse-interface/assets/icons/pls.svg +++ b/packages/synapse-interface/assets/icons/pls.svg @@ -1,90 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/sdt.svg b/packages/synapse-interface/assets/icons/sdt.svg index 6f875ba2c9..0d0824c16c 100644 --- a/packages/synapse-interface/assets/icons/sdt.svg +++ b/packages/synapse-interface/assets/icons/sdt.svg @@ -1,13 +1 @@ - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/sfi.svg b/packages/synapse-interface/assets/icons/sfi.svg index 1cb6836508..e1a8cd0ad2 100644 --- a/packages/synapse-interface/assets/icons/sfi.svg +++ b/packages/synapse-interface/assets/icons/sfi.svg @@ -1,4 +1 @@ - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/solar.svg b/packages/synapse-interface/assets/icons/solar.svg index 94e19c4a88..ed386e2dfa 100644 --- a/packages/synapse-interface/assets/icons/solar.svg +++ b/packages/synapse-interface/assets/icons/solar.svg @@ -1,44 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/susd.svg b/packages/synapse-interface/assets/icons/susd.svg index 8794225fcd..924acb5405 100644 --- a/packages/synapse-interface/assets/icons/susd.svg +++ b/packages/synapse-interface/assets/icons/susd.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/sushi.svg b/packages/synapse-interface/assets/icons/sushi.svg index dc5a7bcf1b..bb4bc618fe 100644 --- a/packages/synapse-interface/assets/icons/sushi.svg +++ b/packages/synapse-interface/assets/icons/sushi.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/syn.svg b/packages/synapse-interface/assets/icons/syn.svg index d4ef052e76..f7a230124d 100644 --- a/packages/synapse-interface/assets/icons/syn.svg +++ b/packages/synapse-interface/assets/icons/syn.svg @@ -1,50 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/unidex.svg b/packages/synapse-interface/assets/icons/unidex.svg index 5e242faf0a..cf432ca520 100644 --- a/packages/synapse-interface/assets/icons/unidex.svg +++ b/packages/synapse-interface/assets/icons/unidex.svg @@ -1,15 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/usdc.svg b/packages/synapse-interface/assets/icons/usdc.svg index 2a3640ffd6..0cf54945bd 100644 --- a/packages/synapse-interface/assets/icons/usdc.svg +++ b/packages/synapse-interface/assets/icons/usdc.svg @@ -1,12 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/usdt.svg b/packages/synapse-interface/assets/icons/usdt.svg index 8da7a84975..1ea97592e0 100644 --- a/packages/synapse-interface/assets/icons/usdt.svg +++ b/packages/synapse-interface/assets/icons/usdt.svg @@ -1,4 +1 @@ - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/vsta.svg b/packages/synapse-interface/assets/icons/vsta.svg index 19f623e8ff..5b2b1ac3c2 100644 --- a/packages/synapse-interface/assets/icons/vsta.svg +++ b/packages/synapse-interface/assets/icons/vsta.svg @@ -1,26 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/wbtc.svg b/packages/synapse-interface/assets/icons/wbtc.svg index 2f8c9b1c02..7f9d25c59b 100644 --- a/packages/synapse-interface/assets/icons/wbtc.svg +++ b/packages/synapse-interface/assets/icons/wbtc.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/packages/synapse-interface/assets/icons/weth.svg b/packages/synapse-interface/assets/icons/weth.svg index 2445cee472..0dec30bb5f 100644 --- a/packages/synapse-interface/assets/icons/weth.svg +++ b/packages/synapse-interface/assets/icons/weth.svg @@ -1,17 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file From 8fe49ece96e01178e177cf43d9f366f187a6cfda Mon Sep 17 00:00:00 2001 From: abtestingalpha Date: Thu, 14 Mar 2024 19:15:22 +0000 Subject: [PATCH 27/29] Publish - @synapsecns/synapse-interface@0.9.7 --- packages/synapse-interface/CHANGELOG.md | 8 ++++++++ packages/synapse-interface/package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/synapse-interface/CHANGELOG.md b/packages/synapse-interface/CHANGELOG.md index 51821779a5..457da831a8 100644 --- a/packages/synapse-interface/CHANGELOG.md +++ b/packages/synapse-interface/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.9.7](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.9.6...@synapsecns/synapse-interface@0.9.7) (2024-03-14) + +**Note:** Version bump only for package @synapsecns/synapse-interface + + + + + ## [0.9.6](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.9.5...@synapsecns/synapse-interface@0.9.6) (2024-03-14) **Note:** Version bump only for package @synapsecns/synapse-interface diff --git a/packages/synapse-interface/package.json b/packages/synapse-interface/package.json index ca691b955c..4e82aa417a 100644 --- a/packages/synapse-interface/package.json +++ b/packages/synapse-interface/package.json @@ -1,6 +1,6 @@ { "name": "@synapsecns/synapse-interface", - "version": "0.9.6", + "version": "0.9.7", "private": true, "engines": { "node": ">=16.0.0" From 50a36343dde64a4585465656793f26ca4ccc22b6 Mon Sep 17 00:00:00 2001 From: lawsonkight Date: Thu, 14 Mar 2024 14:21:47 -0700 Subject: [PATCH 28/29] Fe/compress landing images (#2300) * compress SynapseCircuit image * replace static bridge image on landing --- .../icons/LandingIcons/FauxBridge.tsx | 270 +++++++++ .../icons/LandingIcons/SynapseCircuit.tsx | 530 +----------------- .../pages/landing/sections/BridgeSection.tsx | 23 +- .../landing/sections/SecuritySection.tsx | 13 +- 4 files changed, 304 insertions(+), 532 deletions(-) create mode 100644 packages/synapse-interface/components/icons/LandingIcons/FauxBridge.tsx diff --git a/packages/synapse-interface/components/icons/LandingIcons/FauxBridge.tsx b/packages/synapse-interface/components/icons/LandingIcons/FauxBridge.tsx new file mode 100644 index 0000000000..0dda9d2218 --- /dev/null +++ b/packages/synapse-interface/components/icons/LandingIcons/FauxBridge.tsx @@ -0,0 +1,270 @@ +// import PulseDot from '@/components/icons/PulseDot' +import { CHAINS_ARR } from '@/constants/chains' +import * as BRIDGEABLE from '@constants/tokens/bridgeable' +import { TOKENS_SORTED_BY_SWAPABLETYPE } from '@/constants/tokens' +// import * as WALLET_ICONS from '@components/WalletIcons' + +const cardStyle = + 'text-black dark:text-white bg-zinc-100 dark:bg-bgBase p-3 rounded-[.75rem] border border-zinc-200 dark:border-zinc-800 shadow-xl grid gap-4 max-w-sm' // dark:bg-zinc-900/95 +const sectionStyle = + 'relative bg-zinc-50 dark:bg-bgLight rounded-md px-2.5 py-3 grid gap-1 grid-cols-2 border border-zinc-300 dark:border-transparent' // dark:bg-zinc-800 +const buttonStyle = + 'rounded px-4 py-1 bg-zinc-100 dark:bg-separator border border-zinc-200 dark:border-transparent hover:border-zinc-400 hover:dark:border-zinc-500 h-fit mr-1 cursor-pointer focus:border-zinc-400 focus:dark:borer-zinc-500' // dark:bg-zinc-700 +const chainSelectStyle = + 'flex gap-2 items-center rounded px-2 py-1 bg-inherit border border-zinc-200 dark:border-transparent hover:border-zinc-400 hover:dark:border-zinc-500 active:opacity-70 focus:ring-1 focus:ring-zinc-500 focus:border-transparent' +const tokenSelectStyle = + 'flex gap-2 items-center rounded px-2 py-1.5 bg-inherit dark:bg-separator border border-zinc-200 dark:border-transparent hover:border-zinc-400 hover:dark:border-zinc-500 active:opacity-70 focus:ring-1 focus:ring-zinc-500 focus:border-transparent text-lg ' // dark:bg-zinc-700 +const inputWrapperStyle = + 'relative flex bg-white dark:bg-inherit border border-zinc-200 dark:border-separator rounded-md gap-0 p-1.5 col-span-2 gap-1.5 items-center' // dark:border-zinc-700 +const inputStyle = + 'bg-inherit border-none w-full p-1.5 text-xxl font-normal dark:font-medium tracking-wide rounded placeholder:text-secondary pointer-events-none' + +export default () => { + return ( +
+
+ + + +
+ +
+ + +
+ + +
+ ) +} + +const Select = ({ + type, + defaultName, + label, + data, +}: { + type: 'Chain' | 'Token' + defaultName?: string + label?: string + data: 'volume' | 'count' +}) => { + let button: string + let header: string + let value: number + let reduce: Function + let format: Function + switch (data) { + case 'volume': + button = `Volume by ${type}` + header = '$ vol.' + value = 1000000000 + Math.random() * 100000000 + reduce = () => (value *= 0.85) + format = () => { + if (value >= 1000000) return '$' + (value / 1000000).toFixed(1) + 'M' + let str = value.toFixed(0) + if (value >= 1000) { + for (let i = 3; i < str.length; i += 4) + str = `${str.slice(0, str.length - i)},${str.slice(-i)}` + return '$' + str + } + return '$' + value.toFixed(2) + } + break + case 'count': + button = `Txns by ${type}` + header = 'Txns' + value = 10000 + Math.random() * 1000 + reduce = () => (value *= 0.9) + format = () => { + let str = value.toFixed() + for (let i = 3; i < str.length; i += 4) + str = `${str.slice(0, str.length - i)},${str.slice(-i)}` + return str + } + break + } + + let arr + let key: string + let img: string + let name: string + + switch (type) { + case 'Chain': + arr = CHAINS_ARR + key = 'id' + img = 'chainImg' + name = 'name' + break + case 'Token': + arr = Object.values(BRIDGEABLE) + key = 'name' + img = 'icon' + name = 'symbol' + break + } + + const defaultItem = arr.find((a) => a[name] === defaultName) + + return ( +
+ +
+ + + + + {/* */} + + + + {arr.map((item, i) => { + reduce() + return ( + + + {/* */} + + ) + })} + + +
+ {type} + + {header} +
+ + {item[name]} + {format()}
+
+
+ ) +} + +const SupportedWallets = () => ( +
+
+
Supported wallets
+
    + {/* {Object.values(WALLET_ICONS).map((icon, i) => ( +
  • {icon({ width: 24, height: 24 })}
  • + ))} */} +
+
+ +
+) + +const HistoricMax = () => ( +
+) + +const RightAngle = ({ height }) => { + const width = height / 2 + return ( + + + + ) +} + +const BridgeButton = () => ( + +) diff --git a/packages/synapse-interface/components/icons/LandingIcons/SynapseCircuit.tsx b/packages/synapse-interface/components/icons/LandingIcons/SynapseCircuit.tsx index eecbb38f5d..5b17274247 100644 --- a/packages/synapse-interface/components/icons/LandingIcons/SynapseCircuit.tsx +++ b/packages/synapse-interface/components/icons/LandingIcons/SynapseCircuit.tsx @@ -1,516 +1,32 @@ -export function SynapseCircuitSmall() { +export default function SynapseCircuit() { return ( - - - - - - - - - ) -} - -export function SynapseCircuit() { - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + ) } diff --git a/packages/synapse-interface/pages/landing/sections/BridgeSection.tsx b/packages/synapse-interface/pages/landing/sections/BridgeSection.tsx index 949e96ce3f..2c3bcc7d5e 100644 --- a/packages/synapse-interface/pages/landing/sections/BridgeSection.tsx +++ b/packages/synapse-interface/pages/landing/sections/BridgeSection.tsx @@ -7,6 +7,7 @@ import { BridgeImage, BridgeImageSmall, } from '@/components/icons/LandingIcons/BridgeImage' +import FauxBridge from '@/components/icons/LandingIcons/FauxBridge' import { DeepLiquidityIcon } from '@/components/icons/LandingIcons/DeepLiquidityIcon' import { WideSupportIcon } from '@/components/icons/LandingIcons/WideSupportIcon' import { DeveloperIcon } from '@/components/icons/LandingIcons/DeveloperIcon' @@ -17,33 +18,25 @@ export default function BridgeSection() { styles="flex flex-wrap gap-8 justify-center max-w-4xl m-auto" dataTestId="landing-bridge-section" > -
+

Powering the most popular bridge

- Synapse Bridge is - built on top of the cross-chain infrastructure enabling users to - seamlessly transfer assets across all blockchains. The Bridge has - become the most widely-used method to move assets cross-chain, + Synapse Bridge{' '} + is built on top of the cross-chain infrastructure enabling users + to seamlessly transfer assets across all blockchains. The Bridge + has become the most widely-used method to move assets cross-chain, offering low cost, fast, and secure bridging.

-
- -
-
- -
+
- + }> Swap native assets using our cross-chain AMM liquidity pools diff --git a/packages/synapse-interface/pages/landing/sections/SecuritySection.tsx b/packages/synapse-interface/pages/landing/sections/SecuritySection.tsx index 8671a128e1..baa9500dc1 100644 --- a/packages/synapse-interface/pages/landing/sections/SecuritySection.tsx +++ b/packages/synapse-interface/pages/landing/sections/SecuritySection.tsx @@ -3,10 +3,7 @@ import { SectionContainer, SupportCard, } from '../../../components/landing/shared' -import { - SynapseCircuit, - SynapseCircuitSmall, -} from '@/components/icons/LandingIcons/SynapseCircuit' +import SynapseCircuit from '@/components/icons/LandingIcons/SynapseCircuit' import { SecureIcon } from '@/components/icons/LandingIcons/SecureIcon' import { ExtensibleIcon } from '@/components/icons/LandingIcons/ExtensibleIcon' import { GeneralizedIcon } from '@/components/icons/LandingIcons/GeneralizedIcon' @@ -17,7 +14,7 @@ export default function SecuritySection() { styles="flex flex-wrap gap-8 justify-center max-w-4xl m-auto" dataTestId="landing-security-section" > -
+

@@ -38,11 +35,7 @@ export default function SecuritySection() {

- + }> Synapse’s cross-chain messaging contracts can be deployed across any blockchain From 119f0b0d459e4f57c87b80ad721090bd117b7b57 Mon Sep 17 00:00:00 2001 From: lawsonkight Date: Thu, 14 Mar 2024 21:25:21 +0000 Subject: [PATCH 29/29] Publish - @synapsecns/synapse-interface@0.9.8 --- packages/synapse-interface/CHANGELOG.md | 8 ++++++++ packages/synapse-interface/package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/synapse-interface/CHANGELOG.md b/packages/synapse-interface/CHANGELOG.md index 457da831a8..799822118e 100644 --- a/packages/synapse-interface/CHANGELOG.md +++ b/packages/synapse-interface/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.9.8](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.9.7...@synapsecns/synapse-interface@0.9.8) (2024-03-14) + +**Note:** Version bump only for package @synapsecns/synapse-interface + + + + + ## [0.9.7](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.9.6...@synapsecns/synapse-interface@0.9.7) (2024-03-14) **Note:** Version bump only for package @synapsecns/synapse-interface diff --git a/packages/synapse-interface/package.json b/packages/synapse-interface/package.json index 4e82aa417a..2431c9177f 100644 --- a/packages/synapse-interface/package.json +++ b/packages/synapse-interface/package.json @@ -1,6 +1,6 @@ { "name": "@synapsecns/synapse-interface", - "version": "0.9.7", + "version": "0.9.8", "private": true, "engines": { "node": ">=16.0.0"