From 4a39db467d09431a0b06ea379db9a50fa52e8b4c Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:44:14 +0200 Subject: [PATCH 01/14] refactor(relayer): Factor out common listener utils (#1841) This is a pre-emptive change made to make it easier to reuse common components in alternative listener implementations. Examples for a viem-based listener, as well as an eventual Solana listener. There are subsequent changes in the pipeline to factor out evm-specific parts. --- src/libexec/RelayerSpokePoolIndexer.ts | 139 ++++--------------------- src/libexec/types.ts | 9 ++ src/libexec/util/evm/index.ts | 1 + src/libexec/util/evm/util.ts | 69 ++++++++++++ src/libexec/util/ipc.ts | 43 ++++++++ 5 files changed, 144 insertions(+), 117 deletions(-) create mode 100644 src/libexec/types.ts create mode 100644 src/libexec/util/evm/index.ts create mode 100644 src/libexec/util/evm/util.ts create mode 100644 src/libexec/util/ipc.ts diff --git a/src/libexec/RelayerSpokePoolIndexer.ts b/src/libexec/RelayerSpokePoolIndexer.ts index 951f528e7..e6b211734 100644 --- a/src/libexec/RelayerSpokePoolIndexer.ts +++ b/src/libexec/RelayerSpokePoolIndexer.ts @@ -1,10 +1,8 @@ import assert from "assert"; import minimist from "minimist"; -import { Contract, EventFilter, providers as ethersProviders, utils as ethersUtils } from "ethers"; +import { Contract, providers as ethersProviders, utils as ethersUtils } from "ethers"; import { utils as sdkUtils } from "@across-protocol/sdk"; import * as utils from "../../scripts/utils"; -import { Log } from "../interfaces"; -import { SpokePoolClientMessage } from "../clients"; import { disconnectRedisClients, EventManager, @@ -19,20 +17,13 @@ import { getRedisCache, getWSProviders, Logger, - paginatedEventQuery, - sortEventsAscending, winston, } from "../utils"; +import { postEvents, removeEvent } from "./util/ipc"; +import { ScraperOpts } from "./types"; +import { getEventFilter, getEventFilterArgs, scrapeEvents as _scrapeEvents } from "./util/evm"; type WebSocketProvider = ethersProviders.WebSocketProvider; -type EventSearchConfig = sdkUtils.EventSearchConfig; -type ScraperOpts = { - lookback?: number; // Event lookback (in seconds). - deploymentBlock: number; // SpokePool deployment block - maxBlockRange?: number; // Maximum block range for paginated getLogs queries. - filterArgs?: { [event: string]: string[] }; // Event-specific filter criteria to apply. -}; - const { NODE_SUCCESS, NODE_APP_ERR } = utils; const INDEXER_POLLING_PERIOD = 2_000; // ms; time to sleep between checking for exit request via SIGHUP. @@ -45,108 +36,21 @@ let stop = false; let oldestTime = 0; /** - * Given an event name and contract, return the corresponding Ethers EventFilter object. - * @param contract Ethers Constract instance. - * @param eventName The name of the event to be filtered. - * @param filterArgs Optional filter arguments to be applied. - * @returns An Ethers EventFilter instance. - */ -function getEventFilter(contract: Contract, eventName: string, filterArgs?: string[]): EventFilter { - const filter = contract.filters[eventName]; - if (!isDefined(filter)) { - throw new Error(`Event ${eventName} not defined for contract`); - } - - return isDefined(filterArgs) ? filter(...filterArgs) : filter(); -} - -function getEventFilterArgs(relayer?: string): { [event: string]: string[] } { - const FilledV3Relay = !isDefined(relayer) - ? undefined - : [null, null, null, null, null, null, null, null, null, null, relayer]; - - return { FilledV3Relay }; -} - -/** - * Given the inputs for a SpokePoolClient update, consolidate the inputs into a message and submit it to the parent - * process (if defined). - * @param blockNumber Block number up to which the update applies. - * @param currentTime The SpokePool timestamp at blockNumber. - * @param events An array of Log objects to be submitted. - * @returns void - */ -function postEvents(blockNumber: number, currentTime: number, events: Log[]): void { - if (!isDefined(process.send) || stop) { - return; - } - - // Drop the array component of event.args and retain the named k/v pairs, - // otherwise stringification tends to retain only the array. - events = sortEventsAscending(events); - - const message: SpokePoolClientMessage = { - blockNumber, - currentTime, - oldestTime, - nEvents: events.length, - data: JSON.stringify(events, sdkUtils.jsonReplacerWithBigNumbers), - }; - process.send(JSON.stringify(message)); -} - -/** - * Given an event removal notification, post the message to the parent process. - * @param event Log instance. - * @returns void - */ -function removeEvent(event: Log): void { - if (!isDefined(process.send) || stop) { - return; - } - - const message: SpokePoolClientMessage = { - event: JSON.stringify(event, sdkUtils.jsonReplacerWithBigNumbers), - }; - process.send(JSON.stringify(message)); -} - -/** - * Given a SpokePool contract instance and an event name, scrape all corresponding events and submit them to the - * parent process (if defined). + * Aggregate utils/scrapeEvents for a series of event names. * @param spokePool Ethers Constract instance. - * @param eventName The name of the event to be filtered. + * @param eventNames The array of events to be queried. * @param opts Options to configure event scraping behaviour. * @returns void */ -async function scrapeEvents(spokePool: Contract, eventName: string, opts: ScraperOpts): Promise { - const { lookback, deploymentBlock, filterArgs, maxBlockRange } = opts; - const { provider } = spokePool; - const { chainId } = await provider.getNetwork(); - const chain = getNetworkName(chainId); - - let tStart: number, tStop: number; - - const pollEvents = async (filter: EventFilter, searchConfig: EventSearchConfig): Promise => { - tStart = performance.now(); - const events = await paginatedEventQuery(spokePool, filter, searchConfig); - tStop = performance.now(); - logger.debug({ - at: "SpokePoolIndexer::listen", - message: `Indexed ${events.length} ${chain} events in ${Math.round((tStop - tStart) / 1000)} seconds`, - searchConfig, - }); - return events; - }; - - const { number: toBlock, timestamp: currentTime } = await provider.getBlock("latest"); - const fromBlock = Math.max(toBlock - (lookback ?? deploymentBlock), deploymentBlock); - assert(toBlock > fromBlock, `${toBlock} > ${fromBlock}`); - const searchConfig = { fromBlock, toBlock, maxBlockLookBack: maxBlockRange }; - - const filter = getEventFilter(spokePool, eventName, filterArgs[eventName]); - const events = await pollEvents(filter, searchConfig); - postEvents(toBlock, currentTime, events); +export async function scrapeEvents(spokePool: Contract, eventNames: string[], opts: ScraperOpts): Promise { + const { number: toBlock, timestamp: currentTime } = await spokePool.provider.getBlock("latest"); + const events = await Promise.all( + eventNames.map((eventName) => _scrapeEvents(spokePool, eventName, { ...opts, toBlock }, logger)) + ); + + if (!stop) { + postEvents(toBlock, oldestTime, currentTime, events.flat()); + } } /** @@ -178,7 +82,9 @@ async function listen( // Post an update to the parent. Do this irrespective of whether there were new events or not, since there's // information in blockNumber and currentTime alone. - postEvents(blockNumber, currentTime, events); + if (!stop) { + postEvents(blockNumber, oldestTime, currentTime, events); + } }); // Add a handler for each new instance of a subscribed event. @@ -191,7 +97,9 @@ async function listen( if (event.removed) { eventMgr.remove(event, host); // Notify the parent immediately in case the event was already submitted. - removeEvent(event); + if (!stop) { + removeEvent(event); + } } else { eventMgr.add(event, host); } @@ -277,10 +185,7 @@ async function run(argv: string[]): Promise { if (latestBlock.number > startBlock) { const events = ["V3FundsDeposited", "FilledV3Relay", "RelayedRootBundle", "ExecutedRelayerRefundRoot"]; const _spokePool = spokePool.connect(quorumProvider); - await Promise.all([ - resolveOldestTime(_spokePool, startBlock), - ...events.map((event) => scrapeEvents(_spokePool, event, opts)), - ]); + await Promise.all([resolveOldestTime(_spokePool, startBlock), scrapeEvents(_spokePool, events, opts)]); } // If no lookback was specified then default to the timestamp of the latest block. diff --git a/src/libexec/types.ts b/src/libexec/types.ts new file mode 100644 index 000000000..c1986dfb0 --- /dev/null +++ b/src/libexec/types.ts @@ -0,0 +1,9 @@ +export { Log } from "../interfaces"; +export { SpokePoolClientMessage } from "../clients"; + +export type ScraperOpts = { + lookback?: number; // Event lookback (in seconds). + deploymentBlock: number; // SpokePool deployment block + maxBlockRange?: number; // Maximum block range for paginated getLogs queries. + filterArgs?: { [event: string]: string[] }; // Event-specific filter criteria to apply. +}; diff --git a/src/libexec/util/evm/index.ts b/src/libexec/util/evm/index.ts new file mode 100644 index 000000000..181e76f24 --- /dev/null +++ b/src/libexec/util/evm/index.ts @@ -0,0 +1 @@ +export * from "./util"; diff --git a/src/libexec/util/evm/util.ts b/src/libexec/util/evm/util.ts new file mode 100644 index 000000000..c19a86199 --- /dev/null +++ b/src/libexec/util/evm/util.ts @@ -0,0 +1,69 @@ +import assert from "assert"; +import { Contract, EventFilter } from "ethers"; +import { getNetworkName, isDefined, paginatedEventQuery, winston } from "../../../utils"; +import { Log, ScraperOpts } from "../../types"; + +/** + * Given an event name and contract, return the corresponding Ethers EventFilter object. + * @param contract Ethers Constract instance. + * @param eventName The name of the event to be filtered. + * @param filterArgs Optional filter arguments to be applied. + * @returns An Ethers EventFilter instance. + */ +export function getEventFilter(contract: Contract, eventName: string, filterArgs?: string[]): EventFilter { + const filter = contract.filters[eventName]; + if (!isDefined(filter)) { + throw new Error(`Event ${eventName} not defined for contract`); + } + + return isDefined(filterArgs) ? filter(...filterArgs) : filter(); +} + +/** + * Get a general event filter mapping to be used for filtering SpokePool contract events. + * This is currently only useful for filtering the relayer address on FilledV3Relay events. + * @param relayer Optional relayer address to filter on. + * @returns An argument array for input to an Ethers EventFilter. + */ +export function getEventFilterArgs(relayer?: string): { [event: string]: (null | string)[] } { + const FilledV3Relay = !isDefined(relayer) + ? undefined + : [null, null, null, null, null, null, null, null, null, null, relayer]; + + return { FilledV3Relay }; +} + +/** + * Given a SpokePool contract instance and an event name, scrape all corresponding events and submit them to the + * parent process (if defined). + * @param spokePool Ethers Constract instance. + * @param eventName The name of the event to be filtered. + * @param opts Options to configure event scraping behaviour. + * @returns void + */ +export async function scrapeEvents( + spokePool: Contract, + eventName: string, + opts: ScraperOpts & { toBlock: number }, + logger: winston.Logger +): Promise { + const { lookback, deploymentBlock, filterArgs, maxBlockRange, toBlock } = opts; + const { chainId } = await spokePool.provider.getNetwork(); + const chain = getNetworkName(chainId); + + const fromBlock = Math.max(toBlock - (lookback ?? deploymentBlock), deploymentBlock); + assert(toBlock > fromBlock, `${toBlock} > ${fromBlock}`); + const searchConfig = { fromBlock, toBlock, maxBlockLookBack: maxBlockRange }; + + const tStart = performance.now(); + const filter = getEventFilter(spokePool, eventName, filterArgs[eventName]); + const events = await paginatedEventQuery(spokePool, filter, searchConfig); + const tStop = performance.now(); + logger.debug({ + at: "scrapeEvents", + message: `Scraped ${events.length} ${chain} ${eventName} events in ${Math.round((tStop - tStart) / 1000)} seconds`, + searchConfig, + }); + + return events; +} diff --git a/src/libexec/util/ipc.ts b/src/libexec/util/ipc.ts new file mode 100644 index 000000000..b5bfb81c3 --- /dev/null +++ b/src/libexec/util/ipc.ts @@ -0,0 +1,43 @@ +import { utils as sdkUtils } from "@across-protocol/sdk"; +import { isDefined, sortEventsAscending } from "../../utils"; +import { Log, SpokePoolClientMessage } from "./../types"; + +/** + * Given the inputs for a SpokePoolClient update, consolidate the inputs into a message and submit it to the parent + * process (if defined). + * @param blockNumber Block number up to which the update applies. + * @param currentTime The SpokePool timestamp at blockNumber. + * @param events An array of Log objects to be submitted. + * @returns void + */ +export function postEvents(blockNumber: number, oldestTime: number, currentTime: number, events: Log[]): void { + if (!isDefined(process.send)) { + return; + } + + events = sortEventsAscending(events); + const message: SpokePoolClientMessage = { + blockNumber, + currentTime, + oldestTime, + nEvents: events.length, + data: JSON.stringify(events, sdkUtils.jsonReplacerWithBigNumbers), + }; + process.send(JSON.stringify(message)); +} + +/** + * Given an event removal notification, post the message to the parent process. + * @param event Log instance. + * @returns void + */ +export function removeEvent(event: Log): void { + if (!isDefined(process.send)) { + return; + } + + const message: SpokePoolClientMessage = { + event: JSON.stringify(event, sdkUtils.jsonReplacerWithBigNumbers), + }; + process.send(JSON.stringify(message)); +} From 560abc06405f863057774a28dbfe102bb67b7e9a Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Mon, 30 Sep 2024 18:08:36 +0200 Subject: [PATCH 02/14] feat(relayer): Add viem-based external SpokePool listener (#1842) viem supports keepalives and timeouts on websocket transports. In testing it has appeared to successfully websocket connections for longer than ethers v5. --- package.json | 1 + src/libexec/SpokePoolListenerExperimental.ts | 262 +++++++++++++++++++ yarn.lock | 127 +++++++-- 3 files changed, 362 insertions(+), 28 deletions(-) create mode 100644 src/libexec/SpokePoolListenerExperimental.ts diff --git a/package.json b/package.json index 5e84d3e23..79bc3e84c 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "redis4": "npm:redis@^4.1.0", "superstruct": "^1.0.3", "ts-node": "^10.9.1", + "viem": "^2.21.7", "winston": "^3.10.0", "zksync-ethers": "^5.7.2" }, diff --git a/src/libexec/SpokePoolListenerExperimental.ts b/src/libexec/SpokePoolListenerExperimental.ts new file mode 100644 index 000000000..e5e2b5d31 --- /dev/null +++ b/src/libexec/SpokePoolListenerExperimental.ts @@ -0,0 +1,262 @@ +import assert from "assert"; +import minimist from "minimist"; +import { Contract, providers as ethersProviders, utils as ethersUtils } from "ethers"; +import { BaseError, Block, createPublicClient, Log as viemLog, webSocket } from "viem"; +import * as chains from "viem/chains"; +import { utils as sdkUtils } from "@across-protocol/sdk"; +import * as utils from "../../scripts/utils"; +import { + CHAIN_IDs, + disconnectRedisClients, + EventManager, + exit, + isDefined, + getBlockForTimestamp, + getChainQuorum, + getDeploymentBlockNumber, + getNetworkName, + getNodeUrlList, + getOriginFromURL, + getProvider, + getRedisCache, + Logger, + winston, +} from "../utils"; +import { ScraperOpts } from "./types"; +import { postEvents, removeEvent } from "./util/ipc"; +import { getEventFilterArgs, scrapeEvents as _scrapeEvents } from "./util/evm"; + +const { NODE_SUCCESS, NODE_APP_ERR } = utils; + +const INDEXER_POLLING_PERIOD = 2_000; // ms; time to sleep between checking for exit request via SIGHUP. + +let logger: winston.Logger; +let chainId: number; +let chain: string; +let stop = false; +let oldestTime = 0; + +// This mapping is necessary because viem imposes extremely narrow type inference. @todo: Improve? +const _chains = { + [CHAIN_IDs.ARBITRUM]: chains.arbitrum, + [CHAIN_IDs.BASE]: chains.base, + [CHAIN_IDs.BLAST]: chains.blast, + [CHAIN_IDs.LINEA]: chains.linea, + [CHAIN_IDs.LISK]: chains.lisk, + [CHAIN_IDs.MAINNET]: chains.mainnet, + [CHAIN_IDs.MODE]: chains.mode, + [CHAIN_IDs.OPTIMISM]: chains.optimism, + [CHAIN_IDs.POLYGON]: chains.polygon, + [CHAIN_IDs.REDSTONE]: chains.redstone, + [CHAIN_IDs.SCROLL]: chains.scroll, + [CHAIN_IDs.ZK_SYNC]: chains.zksync, + [CHAIN_IDs.ZORA]: chains.zora, +} as const; + +/** + * Aggregate utils/scrapeEvents for a series of event names. + * @param spokePool Ethers Constract instance. + * @param eventNames The array of events to be queried. + * @param opts Options to configure event scraping behaviour. + * @returns void + */ +export async function scrapeEvents(spokePool: Contract, eventNames: string[], opts: ScraperOpts): Promise { + const { number: toBlock, timestamp: currentTime } = await spokePool.provider.getBlock("latest"); + const events = await Promise.all( + eventNames.map((eventName) => _scrapeEvents(spokePool, eventName, { ...opts, toBlock }, logger)) + ); + + if (!stop) { + postEvents(toBlock, oldestTime, currentTime, events.flat()); + } +} + +/** + * Given a SpokePool contract instance and an array of event names, subscribe to all future event emissions. + * Periodically transmit received events to the parent process (if defined). + * @param eventMgr Ethers Constract instance. + * @param eventName The name of the event to be filtered. + * @param opts Options to configure event scraping behaviour. + * @returns void + */ +async function listen(eventMgr: EventManager, spokePool: Contract, eventNames: string[], quorum = 1): Promise { + const urls = getNodeUrlList(chainId, quorum, "wss"); + let nProviders = urls.length; + assert(nProviders >= quorum, `Insufficient providers for ${chain} (required ${quorum} by quorum)`); + + const providers = urls.map((url) => + createPublicClient({ + chain: _chains[chainId], + transport: webSocket(url, { name: getOriginFromURL(url) }), + }) + ); + + // On each new block, submit any "finalised" events. + const newBlock = (block: Block) => { + const [blockNumber, currentTime] = [parseInt(block.number.toString()), parseInt(block.timestamp.toString())]; + const events = eventMgr.tick(blockNumber); + postEvents(blockNumber, oldestTime, currentTime, events); + }; + + const blockError = (error: Error, provider: string) => { + const at = "RelayerSpokePoolListener::run"; + const message = `Caught ${chain} provider error.`; + const { message: errorMessage, details, shortMessage, metaMessages } = error as BaseError; + logger.debug({ at, message, errorMessage, shortMessage, provider, details, metaMessages }); + + if (!stop && --nProviders < quorum) { + stop = true; + logger.warn({ + at: "RelayerSpokePoolListener::run", + message: `Insufficient ${chain} providers to continue.`, + quorum, + nProviders, + }); + } + }; + + providers.forEach((provider, idx) => { + if (idx === 0) { + provider.watchBlocks({ + emitOnBegin: true, + onBlock: (block: Block) => newBlock(block), + onError: (error: Error) => blockError(error, provider.name), + }); + } + + const abi = JSON.parse(spokePool.interface.format(ethersUtils.FormatTypes.json) as string); + eventNames.forEach((eventName) => { + provider.watchContractEvent({ + address: spokePool.address as `0x${string}`, + abi, + eventName, + onLogs: (logs: viemLog[]) => + logs.forEach((log) => { + const event = { + ...log, + args: log["args"], + blockNumber: Number(log.blockNumber), + event: log["eventName"], + topics: [], // Not supplied by viem, but not actually used by the relayer. + }; + if (log.removed) { + eventMgr.remove(event, provider.name); + removeEvent(event); + } else { + eventMgr.add(event, provider.name); + } + }), + }); + }); + }); + + do { + await sdkUtils.delay(INDEXER_POLLING_PERIOD); + } while (!stop); +} + +/** + * Main entry point. + */ +async function run(argv: string[]): Promise { + const minimistOpts = { + string: ["lookback", "relayer"], + }; + const args = minimist(argv, minimistOpts); + + ({ chainId } = args); + const { lookback, relayer = null, maxBlockRange = 10_000 } = args; + assert(Number.isInteger(chainId), "chainId must be numeric "); + assert(Number.isInteger(maxBlockRange), "maxBlockRange must be numeric"); + assert(!isDefined(relayer) || ethersUtils.isAddress(relayer), `relayer address is invalid (${relayer})`); + + const { quorum = getChainQuorum(chainId) } = args; + assert(Number.isInteger(quorum), "quorum must be numeric "); + + chain = getNetworkName(chainId); + + const quorumProvider = await getProvider(chainId); + const blockFinder = undefined; + const cache = await getRedisCache(); + const latestBlock = await quorumProvider.getBlock("latest"); + + const deploymentBlock = getDeploymentBlockNumber("SpokePool", chainId); + let startBlock = latestBlock.number; + if (/^@[0-9]+$/.test(lookback)) { + // Lookback to a specific block (lookback = @). + startBlock = Number(lookback.slice(1)); + } else if (isDefined(lookback)) { + // Resolve `lookback` seconds from head to a specific block. + assert(Number.isInteger(Number(lookback)), `Invalid lookback (${lookback})`); + startBlock = Math.max( + deploymentBlock, + await getBlockForTimestamp(chainId, latestBlock.timestamp - lookback, blockFinder, cache) + ); + } else { + logger.debug({ at: "RelayerSpokePoolListener::run", message: `Skipping lookback on ${chain}.` }); + } + + const opts = { + quorum, + deploymentBlock, + lookback: latestBlock.number - startBlock, + maxBlockRange, + filterArgs: getEventFilterArgs(relayer), + }; + + logger.debug({ at: "RelayerSpokePoolListener::run", message: `Starting ${chain} SpokePool Indexer.`, opts }); + const spokePool = await utils.getSpokePoolContract(chainId); + + process.on("SIGHUP", () => { + logger.debug({ at: "Relayer#run", message: `Received SIGHUP in ${chain} listener, stopping...` }); + stop = true; + }); + + process.on("disconnect", () => { + logger.debug({ at: "Relayer::run", message: `${chain} parent disconnected, stopping...` }); + stop = true; + }); + + // Note: An event emitted between scrapeEvents() and listen(). @todo: Ensure that there is overlap and dedpulication. + logger.debug({ at: "RelayerSpokePoolListener::run", message: `Scraping previous ${chain} events.`, opts }); + + // The SpokePoolClient reports on the timestamp of the oldest block searched. The relayer likely doesn't need this, + // but resolve it anyway for consistency with the main SpokePoolClient implementation. + const resolveOldestTime = async (spokePool: Contract, blockTag: ethersProviders.BlockTag) => { + oldestTime = (await spokePool.getCurrentTime({ blockTag })).toNumber(); + }; + + if (latestBlock.number > startBlock) { + const events = ["V3FundsDeposited", "FilledV3Relay", "RelayedRootBundle", "ExecutedRelayerRefundRoot"]; + const _spokePool = spokePool.connect(quorumProvider); + await Promise.all([resolveOldestTime(_spokePool, startBlock), scrapeEvents(_spokePool, events, opts)]); + } + + // If no lookback was specified then default to the timestamp of the latest block. + oldestTime ??= latestBlock.timestamp; + + // Events to listen for. + const events = ["V3FundsDeposited", "FilledV3Relay"]; + const eventMgr = new EventManager(logger, chainId, quorum); + + logger.debug({ at: "RelayerSpokePoolListener::run", message: `Starting ${chain} listener.`, events, opts }); + await listen(eventMgr, spokePool, events, quorum); +} + +if (require.main === module) { + logger = Logger; + + run(process.argv.slice(2)) + .then(() => { + process.exitCode = NODE_SUCCESS; + }) + .catch((error) => { + logger.error({ at: "RelayerSpokePoolListener", message: `${chain} listener exited with error.`, error }); + process.exitCode = NODE_APP_ERR; + }) + .finally(async () => { + await disconnectRedisClients(); + logger.debug({ at: "RelayerSpokePoolListener", message: `Exiting ${chain} listener.` }); + exit(process.exitCode); + }); +} diff --git a/yarn.lock b/yarn.lock index e5e4cbd42..62478b7bf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -74,6 +74,11 @@ superstruct "^0.15.4" tslib "^2.6.2" +"@adraffy/ens-normalize@1.10.0": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" + integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== + "@arbitrum/sdk@^3.1.3": version "3.1.3" resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.1.3.tgz#75236043717a450b569faaa087687c51d525b0c3" @@ -1503,11 +1508,42 @@ resolved "https://registry.yarnpkg.com/@multiformats/base-x/-/base-x-4.0.1.tgz#95ff0fa58711789d53aefb2590a8b7a4e715d121" integrity sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw== +"@noble/curves@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.0.tgz#f05771ef64da724997f69ee1261b2417a49522d6" + integrity sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg== + dependencies: + "@noble/hashes" "1.4.0" + +"@noble/curves@^1.4.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.6.0.tgz#be5296ebcd5a1730fccea4786d420f87abfeb40b" + integrity sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ== + dependencies: + "@noble/hashes" "1.5.0" + +"@noble/curves@~1.4.0": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" + integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== + dependencies: + "@noble/hashes" "1.4.0" + "@noble/hashes@1.0.0", "@noble/hashes@~1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.0.0.tgz#d5e38bfbdaba174805a4e649f13be9a9ed3351ae" integrity sha512-DZVbtY62kc3kkBtMHqwCOfXrT/hnoORy5BJ4+HU1IR59X0KWAOqsfzQPcUl/lQLlG7qXbe/fZ3r/emxtAl+sqg== +"@noble/hashes@1.4.0", "@noble/hashes@~1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" + integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== + +"@noble/hashes@1.5.0", "@noble/hashes@^1.4.0", "@noble/hashes@~1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.5.0.tgz#abadc5ca20332db2b1b2aa3e496e9af1213570b0" + integrity sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA== + "@noble/secp256k1@1.5.5", "@noble/secp256k1@~1.5.2": version "1.5.5" resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.5.5.tgz#315ab5745509d1a8c8e90d0bdf59823ccf9bcfc3" @@ -2373,6 +2409,11 @@ resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.0.0.tgz#109fb595021de285f05a7db6806f2f48296fcee7" integrity sha512-gIVaYhUsy+9s58m/ETjSJVKHhKTBMmcRb9cEV5/5dwvfDlfORjKrFsDeDHWRrm6RjcPvCLZFwGJjAjLj1gg4HA== +"@scure/base@~1.1.6", "@scure/base@~1.1.8": + version "1.1.8" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.8.tgz#8f23646c352f020c83bca750a82789e246d42b50" + integrity sha512-6CyAclxj3Nb0XT7GHK6K4zK6k2xJm6E4Ft0Ohjt4WgegiFUHEtFb2CGzmPmGBwoIhrLsqNLYfLr04Y1GePrzZg== + "@scure/bip32@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.0.1.tgz#1409bdf9f07f0aec99006bb0d5827693418d3aa5" @@ -2382,6 +2423,15 @@ "@noble/secp256k1" "~1.5.2" "@scure/base" "~1.0.0" +"@scure/bip32@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.4.0.tgz#4e1f1e196abedcef395b33b9674a042524e20d67" + integrity sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg== + dependencies: + "@noble/curves" "~1.4.0" + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + "@scure/bip39@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.0.0.tgz#47504e58de9a56a4bbed95159d2d6829fa491bb0" @@ -2390,6 +2440,14 @@ "@noble/hashes" "~1.0.0" "@scure/base" "~1.0.0" +"@scure/bip39@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.4.0.tgz#664d4f851564e2e1d4bffa0339f9546ea55960a6" + integrity sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw== + dependencies: + "@noble/hashes" "~1.5.0" + "@scure/base" "~1.1.8" + "@sentry/core@5.30.0": version "5.30.0" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" @@ -3414,6 +3472,11 @@ abbrev@1.0.x: web3-eth-abi "^1.2.1" web3-utils "^1.2.1" +abitype@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.5.tgz#29d0daa3eea867ca90f7e4123144c1d1270774b6" + integrity sha512-YzDhti7cjlfaBhHutMaboYB21Ha3rXR9QTkNJFzYC4kC8YclaiwPBBBJY8ejFdu2wnJeZCVZSMlQJ7fi8S6hsw== + abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" @@ -9030,6 +9093,11 @@ isomorphic-unfetch@^3.0.0: node-fetch "^2.6.1" unfetch "^4.2.0" +isows@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.4.tgz#810cd0d90cc4995c26395d2aa4cfa4037ebdf061" + integrity sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ== + isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -13619,7 +13687,7 @@ string-format@^2.0.0: resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -13645,15 +13713,6 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" @@ -13723,7 +13782,7 @@ stringify-package@^1.0.1: resolved "https://registry.yarnpkg.com/stringify-package/-/stringify-package-1.0.1.tgz#e5aa3643e7f74d0f28628b72f3dad5cecfc3ba85" integrity sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg== -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -13751,13 +13810,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -14658,6 +14710,21 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +viem@^2.21.7: + version "2.21.7" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.21.7.tgz#c933fd3adb6f771e5c5fe2b4d7a14d8701ddc32f" + integrity sha512-PFgppakInuHX31wHDx1dzAjhj4t6Po6WrWtutDi33z2vabIT0Wv8qT6tl7DLqfLy2NkTqfN2mdshYLeoI5ZHvQ== + dependencies: + "@adraffy/ens-normalize" "1.10.0" + "@noble/curves" "1.4.0" + "@noble/hashes" "1.4.0" + "@scure/bip32" "1.4.0" + "@scure/bip39" "1.4.0" + abitype "1.0.5" + isows "1.0.4" + webauthn-p256 "0.0.5" + ws "8.17.1" + walk-up-path@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/walk-up-path/-/walk-up-path-1.0.0.tgz#d4745e893dd5fd0dbb58dd0a4c6a33d9c9fec53e" @@ -15150,6 +15217,14 @@ web3@1.8.2, web3@^1.6.0: web3-shh "1.8.2" web3-utils "1.8.2" +webauthn-p256@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/webauthn-p256/-/webauthn-p256-0.0.5.tgz#0baebd2ba8a414b21cc09c0d40f9dd0be96a06bd" + integrity sha512-drMGNWKdaixZNobeORVIqq7k5DsRC9FnG201K2QjeOoQLmtSDaSsVZdkg6n5jUALJKcAG++zBPJXmv6hy0nWFg== + dependencies: + "@noble/curves" "^1.4.0" + "@noble/hashes" "^1.4.0" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -15317,7 +15392,7 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -15343,15 +15418,6 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -15381,6 +15447,11 @@ ws@7.4.6: resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== +ws@8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== + ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" From 6b42f7941558f41b93642de586727b04203b5d12 Mon Sep 17 00:00:00 2001 From: bmzig <57361391+bmzig@users.noreply.github.com> Date: Wed, 2 Oct 2024 07:57:10 -0500 Subject: [PATCH 03/14] improve: swap Optimism and Base OpStackAdapters with BaseChainAdapters (#1839) * improve: swap Optimism and Base OpStackAdapters with BaseChainAdapters Signed-off-by: bennett --------- Signed-off-by: bennett --- src/adapter/bridges/SnxOptimismBridge.ts | 36 ++++++++++++++++++--- src/clients/bridges/AdapterManager.ts | 20 ++++++++---- src/common/abi/SnxOptimismBridgeL1.json | 2 +- test/AdapterManager.SendTokensCrossChain.ts | 16 ++++----- test/generic-adapters/OpStack.ts | 20 ++++++------ 5 files changed, 63 insertions(+), 31 deletions(-) diff --git a/src/adapter/bridges/SnxOptimismBridge.ts b/src/adapter/bridges/SnxOptimismBridge.ts index e7cb310f5..791f563a4 100644 --- a/src/adapter/bridges/SnxOptimismBridge.ts +++ b/src/adapter/bridges/SnxOptimismBridge.ts @@ -1,4 +1,12 @@ -import { Contract, BigNumber, paginatedEventQuery, EventSearchConfig, Signer, Provider } from "../../utils"; +import { + Contract, + BigNumber, + paginatedEventQuery, + EventSearchConfig, + Signer, + Provider, + isContractDeployedToAddress, +} from "../../utils"; import { CONTRACT_ADDRESSES } from "../../common"; import { BaseBridgeAdapter, BridgeTransactionDetails, BridgeEvents } from "./BaseBridgeAdapter"; import { processEvent } from "../utils"; @@ -43,11 +51,19 @@ export class SnxOptimismBridge extends BaseBridgeAdapter { toAddress: string, eventConfig: EventSearchConfig ): Promise { - // @dev For the SnxBridge, only the `toAddress` is indexed on the L2 event so we treat the `fromAddress` as the - // toAddress when fetching the L1 event. + const hubPoolAddress = this.getHubPool().address; + // @dev Since the SnxOptimism bridge has no _from field when querying for finalizations, we cannot use + // the hub pool to determine cross chain transfers (since we do not assume knowledge of the spoke pool address). + if (fromAddress === hubPoolAddress) { + return Promise.resolve({}); + } + // If `toAddress` is a contract on L2, then assume the contract is the spoke pool, and further assume that the sender + // is the hub pool. + const isSpokePool = await this.isL2ChainContract(toAddress); + fromAddress = isSpokePool ? hubPoolAddress : fromAddress; const events = await paginatedEventQuery( this.getL1Bridge(), - this.getL1Bridge().filters.DepositInitiated(undefined, toAddress), + this.getL1Bridge().filters.DepositInitiated(fromAddress), eventConfig ); return { @@ -70,4 +86,16 @@ export class SnxOptimismBridge extends BaseBridgeAdapter { [this.resolveL2TokenAddress(l1Token)]: events.map((event) => processEvent(event, "_amount", "_to", "_from")), }; } + + private getHubPool(): Contract { + const hubPoolContractData = CONTRACT_ADDRESSES[this.hubChainId]?.hubPool; + if (!hubPoolContractData) { + throw new Error(`hubPoolContractData not found for chain ${this.hubChainId}`); + } + return new Contract(hubPoolContractData.address, hubPoolContractData.abi, this.l1Signer); + } + + private isL2ChainContract(address: string): Promise { + return isContractDeployedToAddress(address, this.getL2Bridge().provider); + } } diff --git a/src/clients/bridges/AdapterManager.ts b/src/clients/bridges/AdapterManager.ts index ec8a9d732..d23ec0bf8 100644 --- a/src/clients/bridges/AdapterManager.ts +++ b/src/clients/bridges/AdapterManager.ts @@ -9,7 +9,7 @@ import { import { InventoryConfig, OutstandingTransfers } from "../../interfaces"; import { BigNumber, isDefined, winston, Signer, getL2TokenAddresses, TransactionResponse, assert } from "../../utils"; import { SpokePoolClient, HubPoolClient } from "../"; -import { ArbitrumAdapter, PolygonAdapter, ZKSyncAdapter, LineaAdapter, OpStackAdapter, ScrollAdapter } from "./"; +import { ArbitrumAdapter, PolygonAdapter, ZKSyncAdapter, LineaAdapter, ScrollAdapter } from "./"; import { CHAIN_IDs, TOKEN_SYMBOLS_MAP } from "@across-protocol/constants"; import { BaseChainAdapter } from "../../adapter"; @@ -60,12 +60,15 @@ export class AdapterManager { ); }; if (this.spokePoolClients[OPTIMISM] !== undefined) { - this.adapters[OPTIMISM] = new OpStackAdapter( + this.adapters[OPTIMISM] = new BaseChainAdapter( + spokePoolClients, OPTIMISM, + hubChainId, + filterMonitoredAddresses(OPTIMISM), logger, SUPPORTED_TOKENS[OPTIMISM], - spokePoolClients, - filterMonitoredAddresses(OPTIMISM) + constructBridges(OPTIMISM), + DEFAULT_GAS_MULTIPLIER[OPTIMISM] ?? 1 ); } if (this.spokePoolClients[POLYGON] !== undefined) { @@ -78,12 +81,15 @@ export class AdapterManager { this.adapters[ZK_SYNC] = new ZKSyncAdapter(logger, spokePoolClients, filterMonitoredAddresses(ZK_SYNC)); } if (this.spokePoolClients[BASE] !== undefined) { - this.adapters[BASE] = new OpStackAdapter( + this.adapters[BASE] = new BaseChainAdapter( + spokePoolClients, BASE, + hubChainId, + filterMonitoredAddresses(BASE), logger, SUPPORTED_TOKENS[BASE], - spokePoolClients, - filterMonitoredAddresses(BASE) + constructBridges(BASE), + DEFAULT_GAS_MULTIPLIER[BASE] ?? 1 ); } if (this.spokePoolClients[LINEA] !== undefined) { diff --git a/src/common/abi/SnxOptimismBridgeL1.json b/src/common/abi/SnxOptimismBridgeL1.json index dc278956a..4f6d07ae9 100644 --- a/src/common/abi/SnxOptimismBridgeL1.json +++ b/src/common/abi/SnxOptimismBridgeL1.json @@ -3,7 +3,7 @@ "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "_from", "type": "address" }, - { "indexed": true, "internalType": "address", "name": "_to", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "_to", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "_amount", "type": "uint256" } ], "name": "DepositInitiated", diff --git a/test/AdapterManager.SendTokensCrossChain.ts b/test/AdapterManager.SendTokensCrossChain.ts index 235d8053f..f6bd5e77f 100644 --- a/test/AdapterManager.SendTokensCrossChain.ts +++ b/test/AdapterManager.SendTokensCrossChain.ts @@ -126,7 +126,7 @@ describe("AdapterManager: Send tokens cross-chain", async function () { mainnetTokens.bal, // l1 token getL2TokenAddresses(mainnetTokens.bal)[chainId], // l2 token amountToSend, // amount - addAttrib(adapterManager.adapters[chainId]).l2Gas, // l2Gas + addAttrib(adapterManager.adapters[chainId]).bridges[mainnetTokens.bal].l2Gas, // l2Gas "0x" // data ); @@ -142,7 +142,7 @@ describe("AdapterManager: Send tokens cross-chain", async function () { mainnetTokens.usdc, // l1 token TOKEN_SYMBOLS_MAP["USDC.e"].addresses[chainId], // l2 token amountToSend, // amount - addAttrib(adapterManager.adapters[chainId]).l2Gas, // l2Gas + addAttrib(adapterManager.adapters[chainId]).bridges[mainnetTokens.usdc].canonicalBridge.l2Gas, // l2Gas "0x" // data ); @@ -175,7 +175,7 @@ describe("AdapterManager: Send tokens cross-chain", async function () { mainnetTokens.dai, // l1 token getL2TokenAddresses(mainnetTokens.dai)[chainId], // l2 token amountToSend, // amount - addAttrib(adapterManager.adapters[chainId]).l2Gas, // l2Gas + addAttrib(adapterManager.adapters[chainId]).bridges[mainnetTokens.dai].l2Gas, // l2Gas "0x" // data ); @@ -184,7 +184,7 @@ describe("AdapterManager: Send tokens cross-chain", async function () { expect(l1AtomicDepositor.bridgeWethToOvm).to.have.been.calledWith( relayer.address, // to amountToSend, // amount - addAttrib(adapterManager.adapters[chainId]).l2Gas, // l2Gas + addAttrib(adapterManager.adapters[chainId]).bridges[mainnetTokens.weth].l2Gas, // l2Gas chainId // chainId ); }); @@ -354,7 +354,7 @@ describe("AdapterManager: Send tokens cross-chain", async function () { mainnetTokens.usdc, // l1 token TOKEN_SYMBOLS_MAP.USDbC.addresses[chainId], // l2 token amountToSend, // amount - addAttrib(adapterManager.adapters[chainId]).l2Gas, // l2Gas + addAttrib(adapterManager.adapters[chainId]).bridges[mainnetTokens.usdc].canonicalBridge.l2Gas, // l2Gas "0x" // data ); @@ -363,7 +363,7 @@ describe("AdapterManager: Send tokens cross-chain", async function () { mainnetTokens.bal, // l1 token getL2TokenAddresses(mainnetTokens.bal)[chainId], // l2 token amountToSend, // amount - addAttrib(adapterManager.adapters[chainId]).l2Gas, // l2Gas + addAttrib(adapterManager.adapters[chainId]).bridges[mainnetTokens.bal].l2Gas, // l2Gas "0x" // data ); @@ -373,7 +373,7 @@ describe("AdapterManager: Send tokens cross-chain", async function () { mainnetTokens.dai, // l1 token getL2TokenAddresses(mainnetTokens.dai)[chainId], // l2 token amountToSend, // amount - addAttrib(adapterManager.adapters[chainId]).l2Gas, // l2Gas + addAttrib(adapterManager.adapters[chainId]).bridges[mainnetTokens.dai].l2Gas, // l2Gas "0x" // data ); @@ -382,7 +382,7 @@ describe("AdapterManager: Send tokens cross-chain", async function () { expect(l1AtomicDepositor.bridgeWethToOvm).to.have.been.calledWith( relayer.address, // to amountToSend, // amount - addAttrib(adapterManager.adapters[chainId]).l2Gas, // l2Gas + addAttrib(adapterManager.adapters[chainId]).bridges[mainnetTokens.weth].l2Gas, // l2Gas chainId // chainId ); }); diff --git a/test/generic-adapters/OpStack.ts b/test/generic-adapters/OpStack.ts index 18537ec74..cefa2ddf7 100644 --- a/test/generic-adapters/OpStack.ts +++ b/test/generic-adapters/OpStack.ts @@ -183,17 +183,15 @@ describe("Cross Chain Adapter: OP Stack", async function () { describe("Custom bridge: SNX", () => { it("return only relevant L1 bridge init events", async () => { const snxBridge = adapter.bridges[l1SnxAddress]; - await snxBridgeContract.emitDepositInitiated(monitoredEoa, notMonitoredEoa, 1); - await snxBridgeContract.emitDepositInitiated(notMonitoredEoa, monitoredEoa, 1); + await snxBridgeContract.emitDepositInitiated(monitoredEoa, monitoredEoa, 1); + await snxBridgeContract.emitDepositInitiated(notMonitoredEoa, notMonitoredEoa, 1); const events = ( await snxBridge.queryL1BridgeInitiationEvents(l1SnxAddress, monitoredEoa, monitoredEoa, searchConfig) )[l2SnxAddress]; expect(events.length).to.equal(1); - // For the SnxBridge, only the `toAddress` is indexed on the L2 event so we treat the `fromAddress` as the - // toAddress when fetching the L1 event. expect(events[0].to).to.equal(monitoredEoa); - expect(events[0].from).to.equal(notMonitoredEoa); + expect(events[0].from).to.equal(monitoredEoa); }); it("return only relevant L2 bridge finalization events", async () => { @@ -321,8 +319,8 @@ describe("Cross Chain Adapter: OP Stack", async function () { // WETH transfers: 1x outstanding await wethBridgeContract.emitDepositInitiated(atomicDepositorAddress, monitoredEoa, outstandingAmount); // SNX transfers: 1x outstanding, 1x finalized - await snxBridgeContract.emitDepositInitiated(notMonitoredEoa, monitoredEoa, outstandingAmount); - await snxBridgeContract.emitDepositInitiated(notMonitoredEoa, monitoredEoa, finalizedAmount); + await snxBridgeContract.emitDepositInitiated(monitoredEoa, monitoredEoa, outstandingAmount); + await snxBridgeContract.emitDepositInitiated(monitoredEoa, monitoredEoa, finalizedAmount); await snxBridgeContract.emitDepositFinalized(monitoredEoa, finalizedAmount); // DAI transfers: 1x outstanding, 1x finalized await daiBridgeContract.emitDepositInitiated( @@ -371,16 +369,16 @@ describe("Cross Chain Adapter: OP Stack", async function () { // Get deposit tx hashes of outstanding transfers const outstandingWethEvent = ( - await wethBridge.queryL1BridgeInitiationEvents(l1WethAddress, monitoredEoa, undefined, searchConfig) + await wethBridge.queryL1BridgeInitiationEvents(l1WethAddress, monitoredEoa, monitoredEoa, searchConfig) )[l2WethAddress].find((event) => event.amount.toNumber() === outstandingAmount); const outstandingSnxEvent = ( - await snxBridge.queryL1BridgeInitiationEvents(l1SnxAddress, monitoredEoa, undefined, searchConfig) + await snxBridge.queryL1BridgeInitiationEvents(l1SnxAddress, monitoredEoa, monitoredEoa, searchConfig) )[l2SnxAddress].find((event) => event.amount.toNumber() === outstandingAmount); const outstandingDaiEvent = ( - await daiBridge.queryL1BridgeInitiationEvents(l1DaiAddress, monitoredEoa, undefined, searchConfig) + await daiBridge.queryL1BridgeInitiationEvents(l1DaiAddress, monitoredEoa, monitoredEoa, searchConfig) )[l2DaiAddress].find((event) => event.amount.toNumber() === outstandingAmount); const outstandingErc20Event = ( - await erc20Bridge.queryL1BridgeInitiationEvents(l1Erc20Address, monitoredEoa, undefined, searchConfig) + await erc20Bridge.queryL1BridgeInitiationEvents(l1Erc20Address, monitoredEoa, monitoredEoa, searchConfig) )[l2Erc20Address].find((event) => event.amount.toNumber() === outstandingAmount); const outstandingOfMonitored = ( From d3a88d528542075c349ed859c6f8cbfd635b4c0b Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 4 Oct 2024 11:43:45 +0200 Subject: [PATCH 04/14] improve(relayer): Redirect in-protocol swap message (#1848) This message can be quite spammy in the main logging channel, so redirect it to the more acceptably-noisy "unprofitable fills" channel. --- src/relayer/Relayer.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/relayer/Relayer.ts b/src/relayer/Relayer.ts index 31826ce55..5ce2aadea 100644 --- a/src/relayer/Relayer.ts +++ b/src/relayer/Relayer.ts @@ -292,6 +292,7 @@ export class Relayer { at: "Relayer::filterDeposit", message: "Skipping deposit including in-protocol token swap.", deposit, + notificationPath: "across-unprofitable-fills", }); return false; } From 47c156ffc12eb8a8baba721630bb2b1479ff7e7a Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 4 Oct 2024 12:09:02 +0200 Subject: [PATCH 05/14] improve(relayer): Defer deposit version computation (#1847) getUnfilledDeposits() currently unconditionally computes the deposit version (i.e. the ConfigStore VERSION value applicable at the deposit quoteTimestamp), and then filters out all the deposits that have been filled. Determining the relevant version implies a lot of Array.find() calls, all of which is wasted when the object is subsequently discarded. --- src/utils/FillUtils.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/utils/FillUtils.ts b/src/utils/FillUtils.ts index cce7d59b9..010afdc67 100644 --- a/src/utils/FillUtils.ts +++ b/src/utils/FillUtils.ts @@ -32,11 +32,14 @@ export function getUnfilledDeposits( return deposits .map((deposit) => { - const version = hubPoolClient.configStoreClient.getConfigStoreVersionForTimestamp(deposit.quoteTimestamp); const { unfilledAmount, invalidFills } = destinationClient.getValidUnfilledAmountForDeposit(deposit); - return { deposit, version, unfilledAmount, invalidFills }; + return { deposit, unfilledAmount, invalidFills }; }) - .filter(({ unfilledAmount }) => unfilledAmount.gt(bnZero)); + .filter(({ unfilledAmount }) => unfilledAmount.gt(bnZero)) + .map(({ deposit, ...rest }) => { + const version = hubPoolClient.configStoreClient.getConfigStoreVersionForTimestamp(deposit.quoteTimestamp); + return { deposit, ...rest, version }; + }); } export function getAllUnfilledDeposits( From d5bf653a7961a0cdc70720d9474938ca63f45506 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Mon, 7 Oct 2024 19:41:39 +0200 Subject: [PATCH 06/14] fix(relayer): Fix "failed start" chain log message (#1846) --- src/relayer/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/relayer/index.ts b/src/relayer/index.ts index 1c526c189..a0187748e 100644 --- a/src/relayer/index.ts +++ b/src/relayer/index.ts @@ -72,8 +72,10 @@ export async function runRelayer(_logger: winston.Logger, baseSigner: Signer): P continue; } - const badChains = Object.values(spokePoolClients).filter(({ isUpdated }) => !isUpdated); - throw new Error(`Unable to start relayer due to chains ${badChains}`); + const badChains = Object.values(spokePoolClients) + .filter(({ isUpdated }) => !isUpdated) + .map(({ chainId }) => getNetworkName(chainId)); + throw new Error(`Unable to start relayer due to chains ${badChains.join(", ")}`); } // Signal to any existing relayer that a handover is underway, or alternatively From 1af89a2582e569a4cd232f4d3649b65432a5fb5f Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Mon, 7 Oct 2024 20:15:45 +0200 Subject: [PATCH 07/14] improve(spokepool): Dump relayData hash on fill logs (#1849) This implementation is a bit hacky, but it works and is quite useful when supporting third-parties to debug fillStatus queries. --- scripts/spokepool.ts | 10 +++++++++- src/interfaces/index.ts | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/scripts/spokepool.ts b/scripts/spokepool.ts index cef9687cd..4d4d1b056 100644 --- a/scripts/spokepool.ts +++ b/scripts/spokepool.ts @@ -6,6 +6,7 @@ import { Contract, ethers, Signer } from "ethers"; import { LogDescription } from "@ethersproject/abi"; import { constants as sdkConsts, utils as sdkUtils } from "@across-protocol/sdk"; import { ExpandedERC20__factory as ERC20 } from "@across-protocol/contracts"; +import { RelayData } from "../src/interfaces"; import { BigNumber, formatFeePct, @@ -62,11 +63,18 @@ function printDeposit(originChainId: number, log: LogDescription): void { function printFill(destinationChainId: number, log: LogDescription): void { const { originChainId, outputToken } = log.args; const eventArgs = Object.keys(log.args).filter((key) => isNaN(Number(key))); - const padLeft = eventArgs.reduce((acc, cur) => (cur.length > acc ? cur.length : acc), 0); + + const relayDataHash = sdkUtils.getRelayDataHash( + Object.fromEntries(eventArgs.map((arg) => [arg, log.args[arg]])) as RelayData, + destinationChainId + ); + + const padLeft = [...eventArgs, "relayDataHash"].reduce((acc, cur) => (cur.length > acc ? cur.length : acc), 0); const fields = { tokenSymbol: resolveTokenSymbols([outputToken], destinationChainId)[0], ...Object.fromEntries(eventArgs.map((key) => [key, log.args[key]])), + relayDataHash, }; console.log( `Fill for ${getNetworkName(originChainId)} deposit # ${log.args.depositId}:\n` + diff --git a/src/interfaces/index.ts b/src/interfaces/index.ts index 783e38024..5cbdeac7d 100644 --- a/src/interfaces/index.ts +++ b/src/interfaces/index.ts @@ -52,6 +52,7 @@ export type SetPoolRebalanceRoot = interfaces.SetPoolRebalanceRoot; export type PendingRootBundle = interfaces.PendingRootBundle; // SpokePool interfaces +export type RelayData = interfaces.RelayData; export type FundsDepositedEvent = interfaces.FundsDepositedEvent; export type Deposit = interfaces.Deposit; export type DepositWithBlock = interfaces.DepositWithBlock; From bffa498f95def75927dacdc4cd47d56da23cac26 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Mon, 7 Oct 2024 21:18:41 +0200 Subject: [PATCH 08/14] chore: Bump SDK (#1850) This includes a change that speeds up deposit/fill matching. In the relayer this can save multiple seconds per loop, so it's going to have a meaningful impact on performance. --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 79bc3e84c..b08a3bee0 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "dependencies": { "@across-protocol/constants": "^3.1.14", "@across-protocol/contracts": "^3.0.10", - "@across-protocol/sdk": "^3.2.0", + "@across-protocol/sdk": "^3.2.4", "@arbitrum/sdk": "^3.1.3", "@consensys/linea-sdk": "^0.2.1", "@defi-wonderland/smock": "^2.3.5", diff --git a/yarn.lock b/yarn.lock index 62478b7bf..dfd213345 100644 --- a/yarn.lock +++ b/yarn.lock @@ -50,10 +50,10 @@ axios "^1.6.2" zksync-web3 "^0.14.3" -"@across-protocol/sdk@^3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@across-protocol/sdk/-/sdk-3.2.0.tgz#bd011965c7c3ffc6c76c9e00bb9baa5f80d33c7d" - integrity sha512-ks+A9fvXMdcstedvMzV+uTAFObSuXs/4xSm11CEIMu2RfgGTQe/pCN0KSqPhW+H4v53sblxGJpsL8Y/msfH/HQ== +"@across-protocol/sdk@^3.2.4": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@across-protocol/sdk/-/sdk-3.2.4.tgz#3c7b9dac1c289ca6161c61358f3efb56e97d8d49" + integrity sha512-3/BzwgQdsWv4MsFsmj5OsmjV66QHHBfAuefPOA/TmPK9PC6CAgpNZNuNmp17Kk5pgagy3UDwBF7EDvWLY+aOhQ== dependencies: "@across-protocol/across-token" "^1.0.0" "@across-protocol/constants" "^3.1.14" From a6260543cbfc9971fa31a03d461514b2d30043c3 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Thu, 10 Oct 2024 01:05:02 +0200 Subject: [PATCH 09/14] feat: Support World Chain (#1855) Co-authored-by: bmzig <57361391+bmzig@users.noreply.github.com> --- contracts/AtomicWethDepositor.sol | 3 ++ deployments/mainnet/AtomicWethDepositor.json | 41 ++++++++++++------- .../0b9a38081e5f67aae8aeed6c044fb8c5.json | 21 ++++++++++ package.json | 6 +-- src/clients/ProfitClient.ts | 1 + src/clients/bridges/AdapterManager.ts | 12 ++++++ src/common/Constants.ts | 41 +++++++++++++++++-- src/common/ContractAddresses.ts | 15 ++++++- src/relayer/Relayer.ts | 7 +++- test/Dataworker.loadData.slowFill.ts | 2 + test/Relayer.BasicFill.ts | 9 ++-- test/Relayer.SlowFill.ts | 1 + yarn.lock | 39 ++++++++---------- 13 files changed, 150 insertions(+), 48 deletions(-) create mode 100644 deployments/mainnet/solcInputs/0b9a38081e5f67aae8aeed6c044fb8c5.json diff --git a/contracts/AtomicWethDepositor.sol b/contracts/AtomicWethDepositor.sol index 41680f5ec..2808bf81d 100644 --- a/contracts/AtomicWethDepositor.sol +++ b/contracts/AtomicWethDepositor.sol @@ -52,6 +52,7 @@ contract AtomicWethDepositor { OvmL1Bridge public immutable liskL1Bridge = OvmL1Bridge(0x2658723Bf70c7667De6B25F99fcce13A16D25d08); OvmL1Bridge public immutable redstoneL1Bridge = OvmL1Bridge(0xc473ca7E02af24c129c2eEf51F2aDf0411c1Df69); OvmL1Bridge public immutable blastL1Bridge = OvmL1Bridge(0x697402166Fbf2F22E970df8a6486Ef171dbfc524); + OvmL1Bridge public immutable worldChainL1Bridge = OvmL1Bridge(0x470458C91978D2d929704489Ad730DC3E3001113); OvmL1Bridge public immutable zoraL1Bridge = OvmL1Bridge(0x3e2Ea9B92B7E48A52296fD261dc26fd995284631); PolygonL1Bridge public immutable polygonL1Bridge = PolygonL1Bridge(0xA0c68C638235ee32657e8f720a23ceC1bFc77C77); ZkSyncL1Bridge public immutable zkSyncL1Bridge = ZkSyncL1Bridge(0x32400084C286CF3E17e7B677ea9583e60a000324); @@ -72,6 +73,8 @@ contract AtomicWethDepositor { baseL1Bridge.depositETHTo{ value: amount }(to, l2Gas, ""); } else if (chainId == 34443) { modeL1Bridge.depositETHTo{ value: amount }(to, l2Gas, ""); + } else if (chainId == 480) { + worldChainL1Bridge.depositETHTo{ value: amount }(to, l2Gas, ""); } else if (chainId == 1135) { liskL1Bridge.depositETHTo{ value: amount }(to, l2Gas, ""); } else if (chainId == 81457) { diff --git a/deployments/mainnet/AtomicWethDepositor.json b/deployments/mainnet/AtomicWethDepositor.json index ccd2388ee..39a63f12b 100644 --- a/deployments/mainnet/AtomicWethDepositor.json +++ b/deployments/mainnet/AtomicWethDepositor.json @@ -1,5 +1,5 @@ { - "address": "0xE48278aD2b9b402A8E3C2E0ffbaD7EEe3905bf94", + "address": "0xa679201903847f3723Dc88CA7530c8B665bC51a5", "abi": [ { "anonymous": false, @@ -313,6 +313,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "worldChainL1Bridge", + "outputs": [ + { + "internalType": "contract OvmL1Bridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "zkSyncL1Bridge", @@ -344,26 +357,26 @@ "type": "receive" } ], - "transactionHash": "0xe66a3a0652de755c60dfb9631a85d0a691362b8b3168845b0a98e140976d8fc8", + "transactionHash": "0xc357db947a4f937ca325e6246f6a6bcd972b4ad32ad2bcb66741f8f24b1b8ff0", "receipt": { "to": null, "from": "0x9A8f92a830A5cB89a3816e3D267CB7791c16b04D", - "contractAddress": "0xE48278aD2b9b402A8E3C2E0ffbaD7EEe3905bf94", - "transactionIndex": 120, - "gasUsed": "1317812", + "contractAddress": "0xa679201903847f3723Dc88CA7530c8B665bC51a5", + "transactionIndex": 158, + "gasUsed": "1379246", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x42c5ec9b27101c0ec10f47883073ed42b147572414e2ae70e19082b578abc7ac", - "transactionHash": "0xe66a3a0652de755c60dfb9631a85d0a691362b8b3168845b0a98e140976d8fc8", + "blockHash": "0xbeddf54fffcd886bbc27d552bd71808d082946081f8bf53c058a429a8a0331ec", + "transactionHash": "0xc357db947a4f937ca325e6246f6a6bcd972b4ad32ad2bcb66741f8f24b1b8ff0", "logs": [], - "blockNumber": 20512566, - "cumulativeGasUsed": "13084477", + "blockNumber": 20927440, + "cumulativeGasUsed": "14135373", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 8, - "solcInputHash": "dfa1a8c5a6b030fb38fb617a6ddc8435", - "metadata": "{\"compiler\":{\"version\":\"0.8.23+commit.f704f362\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LineaEthDepositInitiated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"OvmEthDepositInitiated\",\"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\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ZkSyncEthDepositInitiated\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"baseL1Bridge\",\"outputs\":[{\"internalType\":\"contract OvmL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blastL1Bridge\",\"outputs\":[{\"internalType\":\"contract OvmL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bobaL1Bridge\",\"outputs\":[{\"internalType\":\"contract OvmL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"bridgeWethToLinea\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"l2Gas\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"}],\"name\":\"bridgeWethToOvm\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"bridgeWethToPolygon\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"l2GasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"l2GasPerPubdataByteLimit\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"refundRecipient\",\"type\":\"address\"}],\"name\":\"bridgeWethToZkSync\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lineaL1MessageService\",\"outputs\":[{\"internalType\":\"contract LineaL1MessageService\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liskL1Bridge\",\"outputs\":[{\"internalType\":\"contract OvmL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"modeL1Bridge\",\"outputs\":[{\"internalType\":\"contract OvmL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"optimismL1Bridge\",\"outputs\":[{\"internalType\":\"contract OvmL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"polygonL1Bridge\",\"outputs\":[{\"internalType\":\"contract PolygonL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redstoneL1Bridge\",\"outputs\":[{\"internalType\":\"contract OvmL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract Weth\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"zkSyncL1Bridge\",\"outputs\":[{\"internalType\":\"contract ZkSyncL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"zoraL1Bridge\",\"outputs\":[{\"internalType\":\"contract OvmL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Contract deployed on Ethereum helps relay bots atomically unwrap and bridge WETH over the canonical chain bridges for Optimism, Base, Boba, ZkSync, Linea, and Polygon. Needed as these chains only support bridging of ETH, not WETH.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/AtomicWethDepositor.sol\":\"AtomicWethDepositor\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"contracts/AtomicWethDepositor.sol\":{\"keccak256\":\"0xf3a524efe64fbe7ec5fc1635059a8852ab919eff0edddd4c5397fdd306685f0e\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://5448a851d7804aba3805779e13489e3a8b1546f701bb408628fbe414917c5bc3\",\"dweb:/ipfs/QmfP1BybGNvXiBbd5ba2EXNBvr3w1YyoZAWiAUEV3wt9US\"]}},\"version\":1}", - "bytecode": "0x610200806040523461021e5773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26080527399c9fc46f92e8a1c0dec1b1747d010903e884be160a05273735adbbe72226bd52e818e7181953f42e3b0ff2160c05273dc1664458d2f0b6090bea60a8793a4e66c2f1c0060e05261010090733154cf16ccdb4c6d922629664174b904d80f2c358252610120732658723bf70c7667de6b25f99fcce13a16d25d08815261014073c473ca7e02af24c129c2eef51f2adf0411c1df69815261016073697402166fbf2f22e970df8a6486ef171dbfc5248152610180733e2ea9b92b7e48a52296fd261dc26fd99528463181526101a09173a0c68c638235ee32657e8f720a23cec1bfc77c7783526101c0937332400084c286cf3e17e7b677ea9583e60a00032485526101e09573d19d4b5d358258f05d7b411e21a1460d11b0876f875261170798896102238a396080518981816101bb01528181610b6901528181610f0201528181610f780152611223015260a0518981816102940152610933015260c0518981816104700152610d46015260e0518981816107ac015261160f0152518881816103a20152610a80015251878181610128015261051401525186818161065d0152610aef0152518581816105b90152610db50152518481816107020152610e930152518381816109a20152610c3a015251828181610e24015281816111e30152818161131901526113d8015251818181610a1101526110490152f35b5f80fdfe6080806040526004908136101561001d575b5050361561001b57005b005b5f915f3560e01c918263019f8e81146115c757508163128d5f681461113e57816336918a9714610f265781633fc8cef314610eb75781634fbf95d714610e485781635970eafa14610dd957816362c8eb5c14610d6a578163645b6f1114610cfb57828263b3d5ccc314610b1357508163b6865d6e14610aa4578163b745c3f314610a35578163c04b9534146109c6578163c80dcc3814610957578163d3cdc8f9146108e8578163e88650c41461014f575063f43873c4146100de5780610011565b3461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b80fd5b9050346108e45760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108e457610188611633565b604435916024359163ffffffff8416840361038357846064359473ffffffffffffffffffffffffffffffffffffffff93847f000000000000000000000000000000000000000000000000000000000000000016803b1561039257604080517f23b872dd0000000000000000000000000000000000000000000000000000000081523384820190815230602082015291820189905290859082908190606001038183865af19081156108d95785916108c5575b5050803b15610392578380916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528c888401525af19081156108ba5784916108a2575b5050600a870361039657847f00000000000000000000000000000000000000000000000000000000000000001691823b156103925761032c9285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b03925af180156103875761036f575b50505b60405192835216917fcde53d24289bf7d0b2baeea6140c533d8388fb574b055364d718f637bedea7a460203393a480f35b61037890611656565b61038357845f61033b565b8480fd5b6040513d84823e3d90fd5b8380fd5b612105870361046457847f00000000000000000000000000000000000000000000000000000000000000001691823b156103925761043a9285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b03925af1801561038757610450575b505061033e565b61045990611656565b61038357845f610449565b61868b870361050857847f00000000000000000000000000000000000000000000000000000000000000001691823b156103925761043a9285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b61046f87036105ac57847f00000000000000000000000000000000000000000000000000000000000000001691823b156103925761043a9285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b62013e31870361065157847f00000000000000000000000000000000000000000000000000000000000000001691823b156103925761043a9285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b6102b287036106f557847f00000000000000000000000000000000000000000000000000000000000000001691823b156103925761043a9285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b6276adf1870361079a57847f00000000000000000000000000000000000000000000000000000000000000001691823b156103925761043a9285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b909150610120860361084457908691847f00000000000000000000000000000000000000000000000000000000000000001691823b156103925761043a9285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b6064906020604051917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601360248201527f496e76616c6964204f564d20636861696e4964000000000000000000000000006044820152fd5b6108ab90611656565b6108b657825f610287565b8280fd5b6040513d86823e3d90fd5b6108ce90611656565b61039257835f61023a565b6040513d87823e3d90fd5b5080fd5b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b915034610cf85760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610cf857610b4c611633565b6024359073ffffffffffffffffffffffffffffffffffffffff90817f000000000000000000000000000000000000000000000000000000000000000016803b15610cb657604080517f23b872dd0000000000000000000000000000000000000000000000000000000081523387820190815230602082015291820186905290879082908190606001038183865af1908115610ced578791610cd9575b5050803b15610cb6578580916024604051809481937f2e1a7d4d000000000000000000000000000000000000000000000000000000008352898b8401525af1908115610cce578691610cba575b5050817f00000000000000000000000000000000000000000000000000000000000000001690813b15610cb657859360249260405196879586947f4faa8a2600000000000000000000000000000000000000000000000000000000865216908401525af1801561038757610ca65750f35b610caf90611656565b61014c5780f35b8580fd5b610cc390611656565b61038357845f610c35565b6040513d88823e3d90fd5b610ce290611656565b610cb657855f610be8565b6040513d89823e3d90fd5b50fd5b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b905060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108e457610f5a611633565b826024359173ffffffffffffffffffffffffffffffffffffffff90817f000000000000000000000000000000000000000000000000000000000000000016803b1561039257604080517f23b872dd0000000000000000000000000000000000000000000000000000000081523388820190815230602082015291820187905290859082908190606001038183865af19081156108d957859161112a575b5050803b15610392578380916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528a8c8401525af19081156108ba578491611116575b5050817f000000000000000000000000000000000000000000000000000000000000000016916110743486611697565b833b1561038357849260849160405195869485937f9f3ce55a00000000000000000000000000000000000000000000000000000000855216809a840152346024840152606060448401528560648401525af1801561038757611102575b50506040519081527f61ed67a945fe5f4d777919629ad666c7e81d66dc5fbaf4c143edd000c15d67dd60203392a380f35b61110b90611656565b6108b657825f6110d1565b61111f90611656565b6108b657825f611044565b61113390611656565b61039257835f610ff7565b823461155b5760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261155b57611176611633565b602490604435906064359460843573ffffffffffffffffffffffffffffffffffffffff9384821680920361155b576040517fb473318e0000000000000000000000000000000000000000000000000000000081523a848201528187820152886044820152602081606481897f0000000000000000000000000000000000000000000000000000000000000000165afa8015611550575f9061155f575b61121f9150873590611697565b91857f000000000000000000000000000000000000000000000000000000000000000016803b1561155b57604080517f23b872dd00000000000000000000000000000000000000000000000000000000815233878201908152306020820152918201869052905f9082908190606001038183865af180156115505761153d575b50803b156115395788809189604051809481937f2e1a7d4d000000000000000000000000000000000000000000000000000000008352898b8401525af1801561152e5790899161151a575b505060405191602083019280841067ffffffffffffffff8511176114ef57899a8460409b98999a9b52878252897f0000000000000000000000000000000000000000000000000000000000000000163b156114eb5760409a989695949a99979951957feb6724190000000000000000000000000000000000000000000000000000000087528888169087015288358987015260e060448701528960e48701526101048601926064870152608486015261010060a48601525180915261012490818501918160051b860101999189905b82821061144d575050505082809281808b8b979560c4899701520391887f0000000000000000000000000000000000000000000000000000000000000000165af1801561038757611439575b50506040519235835216907fa3e601130860a6f97b42655ad74f631ddf0c8e5adaa98402fded9c09bc35a44060203392a380f35b61144290611656565b610392578385611405565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedc878d969596030181528b855180518092528c5b8281106114d5575050808d0160209081018d9052601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909c018c019b939484019360019290920191016113b9565b808f602082818095870101519201015201611481565b8780fd5b886041877f4e487b71000000000000000000000000000000000000000000000000000000005f52525ffd5b61152390611656565b6114eb57878a6112ea565b6040513d8b823e3d90fd5b8880fd5b611548919950611656565b5f978a61129f565b6040513d5f823e3d90fd5b5f80fd5b5060203d6020116115c0575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f820116820182811067ffffffffffffffff8211176114ef5760209183916040528101031261155b5761121f9051611212565b503d61156b565b3461155b575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261155b5760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361155b57565b67ffffffffffffffff811161166a57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b919082018092116116a457565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffdfea26469706673582212205888bf681cf0d9036082fce3d2d0a7cbdfb2d39c83fdb5d03d2fff0b90c6af1064736f6c63430008170033", - "deployedBytecode": "0x6080806040526004908136101561001d575b5050361561001b57005b005b5f915f3560e01c918263019f8e81146115c757508163128d5f681461113e57816336918a9714610f265781633fc8cef314610eb75781634fbf95d714610e485781635970eafa14610dd957816362c8eb5c14610d6a578163645b6f1114610cfb57828263b3d5ccc314610b1357508163b6865d6e14610aa4578163b745c3f314610a35578163c04b9534146109c6578163c80dcc3814610957578163d3cdc8f9146108e8578163e88650c41461014f575063f43873c4146100de5780610011565b3461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b80fd5b9050346108e45760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108e457610188611633565b604435916024359163ffffffff8416840361038357846064359473ffffffffffffffffffffffffffffffffffffffff93847f000000000000000000000000000000000000000000000000000000000000000016803b1561039257604080517f23b872dd0000000000000000000000000000000000000000000000000000000081523384820190815230602082015291820189905290859082908190606001038183865af19081156108d95785916108c5575b5050803b15610392578380916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528c888401525af19081156108ba5784916108a2575b5050600a870361039657847f00000000000000000000000000000000000000000000000000000000000000001691823b156103925761032c9285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b03925af180156103875761036f575b50505b60405192835216917fcde53d24289bf7d0b2baeea6140c533d8388fb574b055364d718f637bedea7a460203393a480f35b61037890611656565b61038357845f61033b565b8480fd5b6040513d84823e3d90fd5b8380fd5b612105870361046457847f00000000000000000000000000000000000000000000000000000000000000001691823b156103925761043a9285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b03925af1801561038757610450575b505061033e565b61045990611656565b61038357845f610449565b61868b870361050857847f00000000000000000000000000000000000000000000000000000000000000001691823b156103925761043a9285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b61046f87036105ac57847f00000000000000000000000000000000000000000000000000000000000000001691823b156103925761043a9285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b62013e31870361065157847f00000000000000000000000000000000000000000000000000000000000000001691823b156103925761043a9285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b6102b287036106f557847f00000000000000000000000000000000000000000000000000000000000000001691823b156103925761043a9285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b6276adf1870361079a57847f00000000000000000000000000000000000000000000000000000000000000001691823b156103925761043a9285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b909150610120860361084457908691847f00000000000000000000000000000000000000000000000000000000000000001691823b156103925761043a9285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b6064906020604051917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601360248201527f496e76616c6964204f564d20636861696e4964000000000000000000000000006044820152fd5b6108ab90611656565b6108b657825f610287565b8280fd5b6040513d86823e3d90fd5b6108ce90611656565b61039257835f61023a565b6040513d87823e3d90fd5b5080fd5b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b915034610cf85760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610cf857610b4c611633565b6024359073ffffffffffffffffffffffffffffffffffffffff90817f000000000000000000000000000000000000000000000000000000000000000016803b15610cb657604080517f23b872dd0000000000000000000000000000000000000000000000000000000081523387820190815230602082015291820186905290879082908190606001038183865af1908115610ced578791610cd9575b5050803b15610cb6578580916024604051809481937f2e1a7d4d000000000000000000000000000000000000000000000000000000008352898b8401525af1908115610cce578691610cba575b5050817f00000000000000000000000000000000000000000000000000000000000000001690813b15610cb657859360249260405196879586947f4faa8a2600000000000000000000000000000000000000000000000000000000865216908401525af1801561038757610ca65750f35b610caf90611656565b61014c5780f35b8580fd5b610cc390611656565b61038357845f610c35565b6040513d88823e3d90fd5b610ce290611656565b610cb657855f610be8565b6040513d89823e3d90fd5b50fd5b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461014c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b905060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108e457610f5a611633565b826024359173ffffffffffffffffffffffffffffffffffffffff90817f000000000000000000000000000000000000000000000000000000000000000016803b1561039257604080517f23b872dd0000000000000000000000000000000000000000000000000000000081523388820190815230602082015291820187905290859082908190606001038183865af19081156108d957859161112a575b5050803b15610392578380916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528a8c8401525af19081156108ba578491611116575b5050817f000000000000000000000000000000000000000000000000000000000000000016916110743486611697565b833b1561038357849260849160405195869485937f9f3ce55a00000000000000000000000000000000000000000000000000000000855216809a840152346024840152606060448401528560648401525af1801561038757611102575b50506040519081527f61ed67a945fe5f4d777919629ad666c7e81d66dc5fbaf4c143edd000c15d67dd60203392a380f35b61110b90611656565b6108b657825f6110d1565b61111f90611656565b6108b657825f611044565b61113390611656565b61039257835f610ff7565b823461155b5760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261155b57611176611633565b602490604435906064359460843573ffffffffffffffffffffffffffffffffffffffff9384821680920361155b576040517fb473318e0000000000000000000000000000000000000000000000000000000081523a848201528187820152886044820152602081606481897f0000000000000000000000000000000000000000000000000000000000000000165afa8015611550575f9061155f575b61121f9150873590611697565b91857f000000000000000000000000000000000000000000000000000000000000000016803b1561155b57604080517f23b872dd00000000000000000000000000000000000000000000000000000000815233878201908152306020820152918201869052905f9082908190606001038183865af180156115505761153d575b50803b156115395788809189604051809481937f2e1a7d4d000000000000000000000000000000000000000000000000000000008352898b8401525af1801561152e5790899161151a575b505060405191602083019280841067ffffffffffffffff8511176114ef57899a8460409b98999a9b52878252897f0000000000000000000000000000000000000000000000000000000000000000163b156114eb5760409a989695949a99979951957feb6724190000000000000000000000000000000000000000000000000000000087528888169087015288358987015260e060448701528960e48701526101048601926064870152608486015261010060a48601525180915261012490818501918160051b860101999189905b82821061144d575050505082809281808b8b979560c4899701520391887f0000000000000000000000000000000000000000000000000000000000000000165af1801561038757611439575b50506040519235835216907fa3e601130860a6f97b42655ad74f631ddf0c8e5adaa98402fded9c09bc35a44060203392a380f35b61144290611656565b610392578385611405565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedc878d969596030181528b855180518092528c5b8281106114d5575050808d0160209081018d9052601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909c018c019b939484019360019290920191016113b9565b808f602082818095870101519201015201611481565b8780fd5b886041877f4e487b71000000000000000000000000000000000000000000000000000000005f52525ffd5b61152390611656565b6114eb57878a6112ea565b6040513d8b823e3d90fd5b8880fd5b611548919950611656565b5f978a61129f565b6040513d5f823e3d90fd5b5f80fd5b5060203d6020116115c0575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f820116820182811067ffffffffffffffff8211176114ef5760209183916040528101031261155b5761121f9051611212565b503d61156b565b3461155b575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261155b5760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361155b57565b67ffffffffffffffff811161166a57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b919082018092116116a457565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffdfea26469706673582212205888bf681cf0d9036082fce3d2d0a7cbdfb2d39c83fdb5d03d2fff0b90c6af1064736f6c63430008170033" + "numDeployments": 9, + "solcInputHash": "0b9a38081e5f67aae8aeed6c044fb8c5", + "metadata": "{\"compiler\":{\"version\":\"0.8.23+commit.f704f362\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LineaEthDepositInitiated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"OvmEthDepositInitiated\",\"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\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ZkSyncEthDepositInitiated\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"baseL1Bridge\",\"outputs\":[{\"internalType\":\"contract OvmL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blastL1Bridge\",\"outputs\":[{\"internalType\":\"contract OvmL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bobaL1Bridge\",\"outputs\":[{\"internalType\":\"contract OvmL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"bridgeWethToLinea\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"l2Gas\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"}],\"name\":\"bridgeWethToOvm\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"bridgeWethToPolygon\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"l2GasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"l2GasPerPubdataByteLimit\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"refundRecipient\",\"type\":\"address\"}],\"name\":\"bridgeWethToZkSync\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lineaL1MessageService\",\"outputs\":[{\"internalType\":\"contract LineaL1MessageService\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liskL1Bridge\",\"outputs\":[{\"internalType\":\"contract OvmL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"modeL1Bridge\",\"outputs\":[{\"internalType\":\"contract OvmL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"optimismL1Bridge\",\"outputs\":[{\"internalType\":\"contract OvmL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"polygonL1Bridge\",\"outputs\":[{\"internalType\":\"contract PolygonL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"redstoneL1Bridge\",\"outputs\":[{\"internalType\":\"contract OvmL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contract Weth\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"worldChainL1Bridge\",\"outputs\":[{\"internalType\":\"contract OvmL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"zkSyncL1Bridge\",\"outputs\":[{\"internalType\":\"contract ZkSyncL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"zoraL1Bridge\",\"outputs\":[{\"internalType\":\"contract OvmL1Bridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Contract deployed on Ethereum helps relay bots atomically unwrap and bridge WETH over the canonical chain bridges for Optimism, Base, Boba, ZkSync, Linea, and Polygon. Needed as these chains only support bridging of ETH, not WETH.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/AtomicWethDepositor.sol\":\"AtomicWethDepositor\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"contracts/AtomicWethDepositor.sol\":{\"keccak256\":\"0x279a415c1fcf0365315770894547b175fb652c77f12627fa86a5ba290a91dbd7\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://05a980264232fb71de48253205b2d6c647c86b73fe677208f7597c97ad5ee7e9\",\"dweb:/ipfs/QmaCzsBFWC9unHJhRWhK35V1BaJfMUfT6iE4HboMxQMoSV\"]}},\"version\":1}", + "bytecode": "0x61022080604052346102475773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26080527399c9fc46f92e8a1c0dec1b1747d010903e884be160a05273735adbbe72226bd52e818e7181953f42e3b0ff2160c05273dc1664458d2f0b6090bea60a8793a4e66c2f1c0060e05261010090733154cf16ccdb4c6d922629664174b904d80f2c358252610120732658723bf70c7667de6b25f99fcce13a16d25d08815261014073c473ca7e02af24c129c2eef51f2adf0411c1df69815261016073697402166fbf2f22e970df8a6486ef171dbfc524815261018073470458c91978d2d929704489ad730dc3e300111381526101a090733e2ea9b92b7e48a52296fd261dc26fd99528463182526101c09273a0c68c638235ee32657e8f720a23cec1bfc77c7784526101e0947332400084c286cf3e17e7b677ea9583e60a00032486526102009673d19d4b5d358258f05d7b411e21a1460d11b0876f8852611825998a61024c8b396080518a81816101c601528181610c1801528181610fb1015281816110270152611341015260a0518a818161029f01526109e2015260c0518a818161047b0152610df5015260e0518a818161085b015261172d0152518981816103ad0152610b2f01525188818161013301526105c301525187818161070c0152610b9e0152518681816106680152610e6401525185818161051f01526112380152518481816107b10152610f42015251838181610a510152610ce9015251828181610ed3015281816113010152818161143701526114f6015251818181610ac001526110f80152f35b5f80fdfe6080806040526004908136101561001d575b5050361561001b57005b005b5f915f3560e01c918263019f8e81146116e557508163128d5f681461125c5781632a8ecb13146111ed57816336918a9714610fd55781633fc8cef314610f665781634fbf95d714610ef75781635970eafa14610e8857816362c8eb5c14610e19578163645b6f1114610daa57828263b3d5ccc314610bc257508163b6865d6e14610b53578163b745c3f314610ae4578163c04b953414610a75578163c80dcc3814610a06578163d3cdc8f914610997578163e88650c41461015a575063f43873c4146100e95780610011565b3461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b80fd5b9050346109935760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261099357610193611751565b604435916024359163ffffffff8416840361038e57846064359473ffffffffffffffffffffffffffffffffffffffff93847f000000000000000000000000000000000000000000000000000000000000000016803b1561039d57604080517f23b872dd0000000000000000000000000000000000000000000000000000000081523384820190815230602082015291820189905290859082908190606001038183865af1908115610988578591610974575b5050803b1561039d578380916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528c888401525af1908115610969578491610951575b5050600a87036103a157847f00000000000000000000000000000000000000000000000000000000000000001691823b1561039d576103379285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b03925af180156103925761037a575b50505b60405192835216917fcde53d24289bf7d0b2baeea6140c533d8388fb574b055364d718f637bedea7a460203393a480f35b61038390611774565b61038e57845f610346565b8480fd5b6040513d84823e3d90fd5b8380fd5b612105870361046f57847f00000000000000000000000000000000000000000000000000000000000000001691823b1561039d576104459285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b03925af180156103925761045b575b5050610349565b61046490611774565b61038e57845f610454565b61868b870361051357847f00000000000000000000000000000000000000000000000000000000000000001691823b1561039d576104459285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b6101e087036105b757847f00000000000000000000000000000000000000000000000000000000000000001691823b1561039d576104459285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b61046f870361065b57847f00000000000000000000000000000000000000000000000000000000000000001691823b1561039d576104459285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b62013e31870361070057847f00000000000000000000000000000000000000000000000000000000000000001691823b1561039d576104459285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b6102b287036107a457847f00000000000000000000000000000000000000000000000000000000000000001691823b1561039d576104459285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b6276adf1870361084957847f00000000000000000000000000000000000000000000000000000000000000001691823b1561039d576104459285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b90915061012086036108f357908691847f00000000000000000000000000000000000000000000000000000000000000001691823b1561039d576104459285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b6064906020604051917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601360248201527f496e76616c6964204f564d20636861696e4964000000000000000000000000006044820152fd5b61095a90611774565b61096557825f610292565b8280fd5b6040513d86823e3d90fd5b61097d90611774565b61039d57835f610245565b6040513d87823e3d90fd5b5080fd5b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b915034610da75760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610da757610bfb611751565b6024359073ffffffffffffffffffffffffffffffffffffffff90817f000000000000000000000000000000000000000000000000000000000000000016803b15610d6557604080517f23b872dd0000000000000000000000000000000000000000000000000000000081523387820190815230602082015291820186905290879082908190606001038183865af1908115610d9c578791610d88575b5050803b15610d65578580916024604051809481937f2e1a7d4d000000000000000000000000000000000000000000000000000000008352898b8401525af1908115610d7d578691610d69575b5050817f00000000000000000000000000000000000000000000000000000000000000001690813b15610d6557859360249260405196879586947f4faa8a2600000000000000000000000000000000000000000000000000000000865216908401525af1801561039257610d555750f35b610d5e90611774565b6101575780f35b8580fd5b610d7290611774565b61038e57845f610ce4565b6040513d88823e3d90fd5b610d9190611774565b610d6557855f610c97565b6040513d89823e3d90fd5b50fd5b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b905060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261099357611009611751565b826024359173ffffffffffffffffffffffffffffffffffffffff90817f000000000000000000000000000000000000000000000000000000000000000016803b1561039d57604080517f23b872dd0000000000000000000000000000000000000000000000000000000081523388820190815230602082015291820187905290859082908190606001038183865af19081156109885785916111d9575b5050803b1561039d578380916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528a8c8401525af19081156109695784916111c5575b5050817f0000000000000000000000000000000000000000000000000000000000000000169161112334866117b5565b833b1561038e57849260849160405195869485937f9f3ce55a00000000000000000000000000000000000000000000000000000000855216809a840152346024840152606060448401528560648401525af18015610392576111b1575b50506040519081527f61ed67a945fe5f4d777919629ad666c7e81d66dc5fbaf4c143edd000c15d67dd60203392a380f35b6111ba90611774565b61096557825f611180565b6111ce90611774565b61096557825f6110f3565b6111e290611774565b61039d57835f6110a6565b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b82346116795760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261167957611294611751565b602490604435906064359460843573ffffffffffffffffffffffffffffffffffffffff93848216809203611679576040517fb473318e0000000000000000000000000000000000000000000000000000000081523a848201528187820152886044820152602081606481897f0000000000000000000000000000000000000000000000000000000000000000165afa801561166e575f9061167d575b61133d91508735906117b5565b91857f000000000000000000000000000000000000000000000000000000000000000016803b1561167957604080517f23b872dd00000000000000000000000000000000000000000000000000000000815233878201908152306020820152918201869052905f9082908190606001038183865af1801561166e5761165b575b50803b156116575788809189604051809481937f2e1a7d4d000000000000000000000000000000000000000000000000000000008352898b8401525af1801561164c57908991611638575b505060405191602083019280841067ffffffffffffffff85111761160d57899a8460409b98999a9b52878252897f0000000000000000000000000000000000000000000000000000000000000000163b156116095760409a989695949a99979951957feb6724190000000000000000000000000000000000000000000000000000000087528888169087015288358987015260e060448701528960e48701526101048601926064870152608486015261010060a48601525180915261012490818501918160051b860101999189905b82821061156b575050505082809281808b8b979560c4899701520391887f0000000000000000000000000000000000000000000000000000000000000000165af1801561039257611557575b50506040519235835216907fa3e601130860a6f97b42655ad74f631ddf0c8e5adaa98402fded9c09bc35a44060203392a380f35b61156090611774565b61039d578385611523565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedc878d969596030181528b855180518092528c5b8281106115f3575050808d0160209081018d9052601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909c018c019b939484019360019290920191016114d7565b808f60208281809587010151920101520161159f565b8780fd5b886041877f4e487b71000000000000000000000000000000000000000000000000000000005f52525ffd5b61164190611774565b61160957878a611408565b6040513d8b823e3d90fd5b8880fd5b611666919950611774565b5f978a6113bd565b6040513d5f823e3d90fd5b5f80fd5b5060203d6020116116de575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f820116820182811067ffffffffffffffff82111761160d576020918391604052810103126116795761133d9051611330565b503d611689565b34611679575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116795760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361167957565b67ffffffffffffffff811161178857604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b919082018092116117c257565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffdfea26469706673582212205607a85a9e0ca52451b4663fa28c093065e7dee23fa38dcc76041544e413a52e64736f6c63430008170033", + "deployedBytecode": "0x6080806040526004908136101561001d575b5050361561001b57005b005b5f915f3560e01c918263019f8e81146116e557508163128d5f681461125c5781632a8ecb13146111ed57816336918a9714610fd55781633fc8cef314610f665781634fbf95d714610ef75781635970eafa14610e8857816362c8eb5c14610e19578163645b6f1114610daa57828263b3d5ccc314610bc257508163b6865d6e14610b53578163b745c3f314610ae4578163c04b953414610a75578163c80dcc3814610a06578163d3cdc8f914610997578163e88650c41461015a575063f43873c4146100e95780610011565b3461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b80fd5b9050346109935760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261099357610193611751565b604435916024359163ffffffff8416840361038e57846064359473ffffffffffffffffffffffffffffffffffffffff93847f000000000000000000000000000000000000000000000000000000000000000016803b1561039d57604080517f23b872dd0000000000000000000000000000000000000000000000000000000081523384820190815230602082015291820189905290859082908190606001038183865af1908115610988578591610974575b5050803b1561039d578380916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528c888401525af1908115610969578491610951575b5050600a87036103a157847f00000000000000000000000000000000000000000000000000000000000000001691823b1561039d576103379285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b03925af180156103925761037a575b50505b60405192835216917fcde53d24289bf7d0b2baeea6140c533d8388fb574b055364d718f637bedea7a460203393a480f35b61038390611774565b61038e57845f610346565b8480fd5b6040513d84823e3d90fd5b8380fd5b612105870361046f57847f00000000000000000000000000000000000000000000000000000000000000001691823b1561039d576104459285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b03925af180156103925761045b575b5050610349565b61046490611774565b61038e57845f610454565b61868b870361051357847f00000000000000000000000000000000000000000000000000000000000000001691823b1561039d576104459285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b6101e087036105b757847f00000000000000000000000000000000000000000000000000000000000000001691823b1561039d576104459285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b61046f870361065b57847f00000000000000000000000000000000000000000000000000000000000000001691823b1561039d576104459285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b62013e31870361070057847f00000000000000000000000000000000000000000000000000000000000000001691823b1561039d576104459285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b6102b287036107a457847f00000000000000000000000000000000000000000000000000000000000000001691823b1561039d576104459285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b6276adf1870361084957847f00000000000000000000000000000000000000000000000000000000000000001691823b1561039d576104459285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b90915061012086036108f357908691847f00000000000000000000000000000000000000000000000000000000000000001691823b1561039d576104459285888694604051968795869485937f9a2ac6d500000000000000000000000000000000000000000000000000000000855284019060809273ffffffffffffffffffffffffffffffffffffffff63ffffffff92168352166020820152606060408201525f60608201520190565b6064906020604051917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601360248201527f496e76616c6964204f564d20636861696e4964000000000000000000000000006044820152fd5b61095a90611774565b61096557825f610292565b8280fd5b6040513d86823e3d90fd5b61097d90611774565b61039d57835f610245565b6040513d87823e3d90fd5b5080fd5b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b915034610da75760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610da757610bfb611751565b6024359073ffffffffffffffffffffffffffffffffffffffff90817f000000000000000000000000000000000000000000000000000000000000000016803b15610d6557604080517f23b872dd0000000000000000000000000000000000000000000000000000000081523387820190815230602082015291820186905290879082908190606001038183865af1908115610d9c578791610d88575b5050803b15610d65578580916024604051809481937f2e1a7d4d000000000000000000000000000000000000000000000000000000008352898b8401525af1908115610d7d578691610d69575b5050817f00000000000000000000000000000000000000000000000000000000000000001690813b15610d6557859360249260405196879586947f4faa8a2600000000000000000000000000000000000000000000000000000000865216908401525af1801561039257610d555750f35b610d5e90611774565b6101575780f35b8580fd5b610d7290611774565b61038e57845f610ce4565b6040513d88823e3d90fd5b610d9190611774565b610d6557855f610c97565b6040513d89823e3d90fd5b50fd5b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b905060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261099357611009611751565b826024359173ffffffffffffffffffffffffffffffffffffffff90817f000000000000000000000000000000000000000000000000000000000000000016803b1561039d57604080517f23b872dd0000000000000000000000000000000000000000000000000000000081523388820190815230602082015291820187905290859082908190606001038183865af19081156109885785916111d9575b5050803b1561039d578380916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528a8c8401525af19081156109695784916111c5575b5050817f0000000000000000000000000000000000000000000000000000000000000000169161112334866117b5565b833b1561038e57849260849160405195869485937f9f3ce55a00000000000000000000000000000000000000000000000000000000855216809a840152346024840152606060448401528560648401525af18015610392576111b1575b50506040519081527f61ed67a945fe5f4d777919629ad666c7e81d66dc5fbaf4c143edd000c15d67dd60203392a380f35b6111ba90611774565b61096557825f611180565b6111ce90611774565b61096557825f6110f3565b6111e290611774565b61039d57835f6110a6565b823461015757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b82346116795760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261167957611294611751565b602490604435906064359460843573ffffffffffffffffffffffffffffffffffffffff93848216809203611679576040517fb473318e0000000000000000000000000000000000000000000000000000000081523a848201528187820152886044820152602081606481897f0000000000000000000000000000000000000000000000000000000000000000165afa801561166e575f9061167d575b61133d91508735906117b5565b91857f000000000000000000000000000000000000000000000000000000000000000016803b1561167957604080517f23b872dd00000000000000000000000000000000000000000000000000000000815233878201908152306020820152918201869052905f9082908190606001038183865af1801561166e5761165b575b50803b156116575788809189604051809481937f2e1a7d4d000000000000000000000000000000000000000000000000000000008352898b8401525af1801561164c57908991611638575b505060405191602083019280841067ffffffffffffffff85111761160d57899a8460409b98999a9b52878252897f0000000000000000000000000000000000000000000000000000000000000000163b156116095760409a989695949a99979951957feb6724190000000000000000000000000000000000000000000000000000000087528888169087015288358987015260e060448701528960e48701526101048601926064870152608486015261010060a48601525180915261012490818501918160051b860101999189905b82821061156b575050505082809281808b8b979560c4899701520391887f0000000000000000000000000000000000000000000000000000000000000000165af1801561039257611557575b50506040519235835216907fa3e601130860a6f97b42655ad74f631ddf0c8e5adaa98402fded9c09bc35a44060203392a380f35b61156090611774565b61039d578385611523565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedc878d969596030181528b855180518092528c5b8281106115f3575050808d0160209081018d9052601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909c018c019b939484019360019290920191016114d7565b808f60208281809587010151920101520161159f565b8780fd5b886041877f4e487b71000000000000000000000000000000000000000000000000000000005f52525ffd5b61164190611774565b61160957878a611408565b6040513d8b823e3d90fd5b8880fd5b611666919950611774565b5f978a6113bd565b6040513d5f823e3d90fd5b5f80fd5b5060203d6020116116de575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f820116820182811067ffffffffffffffff82111761160d576020918391604052810103126116795761133d9051611330565b503d611689565b34611679575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116795760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361167957565b67ffffffffffffffff811161178857604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b919082018092116117c257565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffdfea26469706673582212205607a85a9e0ca52451b4663fa28c093065e7dee23fa38dcc76041544e413a52e64736f6c63430008170033" } diff --git a/deployments/mainnet/solcInputs/0b9a38081e5f67aae8aeed6c044fb8c5.json b/deployments/mainnet/solcInputs/0b9a38081e5f67aae8aeed6c044fb8c5.json new file mode 100644 index 000000000..b44f5bbd5 --- /dev/null +++ b/deployments/mainnet/solcInputs/0b9a38081e5f67aae8aeed6c044fb8c5.json @@ -0,0 +1,21 @@ +{ + "language": "Solidity", + "sources": { + "contracts/AtomicWethDepositor.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\ninterface Weth {\n function withdraw(uint256 _wad) external;\n\n function transferFrom(address _from, address _to, uint256 _wad) external;\n}\n\ninterface OvmL1Bridge {\n function depositETHTo(address _to, uint32 _l2Gas, bytes calldata _data) external payable;\n}\n\ninterface PolygonL1Bridge {\n function depositEtherFor(address _to) external payable;\n}\n\ninterface ZkSyncL1Bridge {\n function requestL2Transaction(\n address _contractL2,\n uint256 _l2Value,\n bytes calldata _calldata,\n uint256 _l2GasLimit,\n uint256 _l2GasPerPubdataByteLimit,\n bytes[] calldata _factoryDeps,\n address _refundRecipient\n ) external payable;\n\n function l2TransactionBaseCost(\n uint256 _gasPrice,\n uint256 _l2GasLimit,\n uint256 _l2GasPerPubdataByteLimit\n ) external pure returns (uint256);\n}\n\ninterface LineaL1MessageService {\n function sendMessage(address _to, uint256 _fee, bytes calldata _calldata) external payable;\n}\n\n/**\n * @notice Contract deployed on Ethereum helps relay bots atomically unwrap and bridge WETH over the canonical chain\n * bridges for Optimism, Base, Boba, ZkSync, Linea, and Polygon. Needed as these chains only support bridging of ETH,\n * not WETH.\n */\n\ncontract AtomicWethDepositor {\n Weth public immutable weth = Weth(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n OvmL1Bridge public immutable optimismL1Bridge = OvmL1Bridge(0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1);\n OvmL1Bridge public immutable modeL1Bridge = OvmL1Bridge(0x735aDBbE72226BD52e818E7181953f42E3b0FF21);\n OvmL1Bridge public immutable bobaL1Bridge = OvmL1Bridge(0xdc1664458d2f0B6090bEa60A8793A4E66c2F1c00);\n OvmL1Bridge public immutable baseL1Bridge = OvmL1Bridge(0x3154Cf16ccdb4C6d922629664174b904d80F2C35);\n OvmL1Bridge public immutable liskL1Bridge = OvmL1Bridge(0x2658723Bf70c7667De6B25F99fcce13A16D25d08);\n OvmL1Bridge public immutable redstoneL1Bridge = OvmL1Bridge(0xc473ca7E02af24c129c2eEf51F2aDf0411c1Df69);\n OvmL1Bridge public immutable blastL1Bridge = OvmL1Bridge(0x697402166Fbf2F22E970df8a6486Ef171dbfc524);\n OvmL1Bridge public immutable worldChainL1Bridge = OvmL1Bridge(0x470458C91978D2d929704489Ad730DC3E3001113);\n OvmL1Bridge public immutable zoraL1Bridge = OvmL1Bridge(0x3e2Ea9B92B7E48A52296fD261dc26fd995284631);\n PolygonL1Bridge public immutable polygonL1Bridge = PolygonL1Bridge(0xA0c68C638235ee32657e8f720a23ceC1bFc77C77);\n ZkSyncL1Bridge public immutable zkSyncL1Bridge = ZkSyncL1Bridge(0x32400084C286CF3E17e7B677ea9583e60a000324);\n LineaL1MessageService public immutable lineaL1MessageService =\n LineaL1MessageService(0xd19d4B5d358258f05D7B411E21A1460D11B0876F);\n\n event ZkSyncEthDepositInitiated(address indexed from, address indexed to, uint256 amount);\n event LineaEthDepositInitiated(address indexed from, address indexed to, uint256 amount);\n event OvmEthDepositInitiated(uint256 indexed chainId, address indexed from, address indexed to, uint256 amount);\n\n function bridgeWethToOvm(address to, uint256 amount, uint32 l2Gas, uint256 chainId) public {\n weth.transferFrom(msg.sender, address(this), amount);\n weth.withdraw(amount);\n\n if (chainId == 10) {\n optimismL1Bridge.depositETHTo{ value: amount }(to, l2Gas, \"\");\n } else if (chainId == 8453) {\n baseL1Bridge.depositETHTo{ value: amount }(to, l2Gas, \"\");\n } else if (chainId == 34443) {\n modeL1Bridge.depositETHTo{ value: amount }(to, l2Gas, \"\");\n } else if (chainId == 480) {\n worldChainL1Bridge.depositETHTo{ value: amount }(to, l2Gas, \"\");\n } else if (chainId == 1135) {\n liskL1Bridge.depositETHTo{ value: amount }(to, l2Gas, \"\");\n } else if (chainId == 81457) {\n blastL1Bridge.depositETHTo{ value: amount }(to, l2Gas, \"\");\n } else if (chainId == 690) {\n redstoneL1Bridge.depositETHTo{ value: amount }(to, l2Gas, \"\");\n } else if (chainId == 7777777) {\n zoraL1Bridge.depositETHTo{ value: amount }(to, l2Gas, \"\");\n } else if (chainId == 288) {\n bobaL1Bridge.depositETHTo{ value: amount }(to, l2Gas, \"\");\n } else {\n revert(\"Invalid OVM chainId\");\n }\n\n emit OvmEthDepositInitiated(chainId, msg.sender, to, amount);\n }\n\n function bridgeWethToPolygon(address to, uint256 amount) public {\n weth.transferFrom(msg.sender, address(this), amount);\n weth.withdraw(amount);\n polygonL1Bridge.depositEtherFor{ value: amount }(to);\n }\n\n function bridgeWethToLinea(address to, uint256 amount) public payable {\n weth.transferFrom(msg.sender, address(this), amount);\n weth.withdraw(amount);\n lineaL1MessageService.sendMessage{ value: amount + msg.value }(to, msg.value, \"\");\n // Emit an event that we can easily track in the Linea-related adapters/finalizers\n emit LineaEthDepositInitiated(msg.sender, to, amount);\n }\n\n function bridgeWethToZkSync(\n address to,\n uint256 amount,\n uint256 l2GasLimit,\n uint256 l2GasPerPubdataByteLimit,\n address refundRecipient\n ) public {\n // The ZkSync Mailbox contract checks that the msg.value of the transaction is enough to cover the transaction base\n // cost. The transaction base cost can be queried from the Mailbox by passing in an L1 \"executed\" gas price,\n // which is the priority fee plus base fee. This is the same as calling tx.gasprice on-chain as the Mailbox\n // contract does here:\n // https://github.com/matter-labs/era-contracts/blob/3a4506522aaef81485d8abb96f5a6394bd2ba69e/ethereum/contracts/zksync/facets/Mailbox.sol#L287\n uint256 l2TransactionBaseCost = zkSyncL1Bridge.l2TransactionBaseCost(\n tx.gasprice,\n l2GasLimit,\n l2GasPerPubdataByteLimit\n );\n uint256 valueToSubmitXChainMessage = l2TransactionBaseCost + amount;\n weth.transferFrom(msg.sender, address(this), valueToSubmitXChainMessage);\n weth.withdraw(valueToSubmitXChainMessage);\n zkSyncL1Bridge.requestL2Transaction{ value: valueToSubmitXChainMessage }(\n to,\n amount,\n \"\",\n l2GasLimit,\n l2GasPerPubdataByteLimit,\n new bytes[](0),\n refundRecipient\n );\n\n // Emit an event that we can easily track in the ZkSyncAdapter because otherwise there is no easy event to\n // track ETH deposit initiations.\n emit ZkSyncEthDepositInitiated(msg.sender, to, amount);\n }\n\n fallback() external payable {}\n\n // Included to remove a compilation warning.\n // NOTE: this should not affect behavior.\n receive() external payable {}\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "viaIR": true, + "outputSelection": { + "*": { + "*": ["abi", "evm.bytecode", "evm.deployedBytecode", "evm.methodIdentifiers", "metadata"], + "": ["ast"] + } + } + } +} diff --git a/package.json b/package.json index b08a3bee0..3861c1f95 100644 --- a/package.json +++ b/package.json @@ -10,9 +10,9 @@ "node": ">=20" }, "dependencies": { - "@across-protocol/constants": "^3.1.14", - "@across-protocol/contracts": "^3.0.10", - "@across-protocol/sdk": "^3.2.4", + "@across-protocol/constants": "^3.1.16", + "@across-protocol/contracts": "^3.0.11", + "@across-protocol/sdk": "^3.2.6", "@arbitrum/sdk": "^3.1.3", "@consensys/linea-sdk": "^0.2.1", "@defi-wonderland/smock": "^2.3.5", diff --git a/src/clients/ProfitClient.ts b/src/clients/ProfitClient.ts index 70a6be144..ec5907e52 100644 --- a/src/clients/ProfitClient.ts +++ b/src/clients/ProfitClient.ts @@ -590,6 +590,7 @@ export class ProfitClient { [CHAIN_IDs.BLAST]: "USDB", [CHAIN_IDs.LISK]: "USDT", // USDC is not yet supported on Lisk, so revert to USDT. @todo: Update. [CHAIN_IDs.REDSTONE]: "WETH", // Redstone only supports WETH. + [CHAIN_IDs.WORLD_CHAIN]: "WETH", // USDC deferred on World Chain. }; const prodRelayer = process.env.RELAYER_FILL_SIMULATION_ADDRESS ?? PROD_RELAYER; const [defaultTestSymbol, relayer] = diff --git a/src/clients/bridges/AdapterManager.ts b/src/clients/bridges/AdapterManager.ts index d23ec0bf8..e232d5089 100644 --- a/src/clients/bridges/AdapterManager.ts +++ b/src/clients/bridges/AdapterManager.ts @@ -146,6 +146,18 @@ export class AdapterManager { if (this.spokePoolClients[SCROLL] !== undefined) { this.adapters[SCROLL] = new ScrollAdapter(logger, spokePoolClients, filterMonitoredAddresses(SCROLL)); } + if (this.spokePoolClients[CHAIN_IDs.WORLD_CHAIN] !== undefined) { + this.adapters[CHAIN_IDs.WORLD_CHAIN] = new BaseChainAdapter( + spokePoolClients, + CHAIN_IDs.WORLD_CHAIN, + hubChainId, + filterMonitoredAddresses(CHAIN_IDs.WORLD_CHAIN), + logger, + SUPPORTED_TOKENS[CHAIN_IDs.WORLD_CHAIN], + constructBridges(CHAIN_IDs.WORLD_CHAIN), + DEFAULT_GAS_MULTIPLIER[CHAIN_IDs.WORLD_CHAIN] ?? 1 + ); + } if (this.spokePoolClients[ZORA] !== undefined) { this.adapters[ZORA] = new BaseChainAdapter( spokePoolClients, diff --git a/src/common/Constants.ts b/src/common/Constants.ts index 2da9646e6..ae817a340 100644 --- a/src/common/Constants.ts +++ b/src/common/Constants.ts @@ -51,6 +51,7 @@ export const DATAWORKER_FAST_LOOKBACK: { [chainId: number]: number } = { [CHAIN_IDs.POLYGON]: 138240, [CHAIN_IDs.REDSTONE]: 172800, // OP stack [CHAIN_IDs.SCROLL]: 115200, // 4 * 24 * 20 * 60, + [CHAIN_IDs.WORLD_CHAIN]: 172800, // OP stack [CHAIN_IDs.ZK_SYNC]: 345600, // 4 * 24 * 60 * 60, [CHAIN_IDs.ZORA]: 172800, // OP stack }; @@ -88,6 +89,7 @@ export const MIN_DEPOSIT_CONFIRMATIONS: { [threshold: number | string]: { [chain [CHAIN_IDs.POLYGON]: 128, // Commonly used finality level for CEX's that accept Polygon deposits [CHAIN_IDs.REDSTONE]: 120, [CHAIN_IDs.SCROLL]: 30, + [CHAIN_IDs.WORLD_CHAIN]: 120, [CHAIN_IDs.ZK_SYNC]: 120, [CHAIN_IDs.ZORA]: 120, }, @@ -103,6 +105,7 @@ export const MIN_DEPOSIT_CONFIRMATIONS: { [threshold: number | string]: { [chain [CHAIN_IDs.POLYGON]: 100, // Probabilistically safe level based on historic Polygon reorgs [CHAIN_IDs.REDSTONE]: 60, [CHAIN_IDs.SCROLL]: 1, + [CHAIN_IDs.WORLD_CHAIN]: 60, [CHAIN_IDs.ZK_SYNC]: 0, [CHAIN_IDs.ZORA]: 60, }, @@ -118,6 +121,7 @@ export const MIN_DEPOSIT_CONFIRMATIONS: { [threshold: number | string]: { [chain [CHAIN_IDs.POLYGON]: 80, [CHAIN_IDs.REDSTONE]: 60, [CHAIN_IDs.SCROLL]: 1, + [CHAIN_IDs.WORLD_CHAIN]: 60, [CHAIN_IDs.ZK_SYNC]: 0, [CHAIN_IDs.ZORA]: 60, }, @@ -141,8 +145,9 @@ export const CHAIN_MAX_BLOCK_LOOKBACK = { [CHAIN_IDs.MODE]: 10000, [CHAIN_IDs.OPTIMISM]: 10000, // Quick [CHAIN_IDs.POLYGON]: 10000, - [CHAIN_IDs.REDSTONE]: 10000, // xxx verify + [CHAIN_IDs.REDSTONE]: 10000, [CHAIN_IDs.SCROLL]: 10000, + [CHAIN_IDs.WORLD_CHAIN]: 10000, [CHAIN_IDs.ZK_SYNC]: 10000, [CHAIN_IDs.ZORA]: 10000, // Testnets: @@ -173,6 +178,7 @@ export const BUNDLE_END_BLOCK_BUFFERS = { [CHAIN_IDs.POLYGON]: 128, // 2s/block. Polygon reorgs often so this number is set larger than the largest observed reorg. [CHAIN_IDs.REDSTONE]: 60, // 2s/block [CHAIN_IDs.SCROLL]: 40, // ~3s/block + [CHAIN_IDs.WORLD_CHAIN]: 60, // 2s/block [CHAIN_IDs.ZK_SYNC]: 120, // ~1s/block. ZkSync is a centralized sequencer but is relatively unstable so this is kept higher than 0 [CHAIN_IDs.ZORA]: 60, // 2s/block // Testnets: @@ -217,6 +223,7 @@ export const CHAIN_CACHE_FOLLOW_DISTANCE: { [chainId: number]: number } = { [CHAIN_IDs.POLYGON]: 256, [CHAIN_IDs.REDSTONE]: 120, [CHAIN_IDs.SCROLL]: 100, + [CHAIN_IDs.WORLD_CHAIN]: 120, [CHAIN_IDs.ZK_SYNC]: 512, [CHAIN_IDs.ZORA]: 120, // Testnets: @@ -246,6 +253,7 @@ export const DEFAULT_NO_TTL_DISTANCE: { [chainId: number]: number } = { [CHAIN_IDs.POLYGON]: 86400, [CHAIN_IDs.REDSTONE]: 86400, [CHAIN_IDs.SCROLL]: 57600, + [CHAIN_IDs.WORLD_CHAIN]: 86400, [CHAIN_IDs.ZK_SYNC]: 172800, [CHAIN_IDs.ZORA]: 86400, }; @@ -261,6 +269,7 @@ export const DEFAULT_GAS_FEE_SCALERS: { [CHAIN_IDs.MODE]: { maxFeePerGasScaler: 2, maxPriorityFeePerGasScaler: 0.01 }, [CHAIN_IDs.OPTIMISM]: { maxFeePerGasScaler: 2, maxPriorityFeePerGasScaler: 0.01 }, [CHAIN_IDs.REDSTONE]: { maxFeePerGasScaler: 2, maxPriorityFeePerGasScaler: 0.01 }, + [CHAIN_IDs.WORLD_CHAIN]: { maxFeePerGasScaler: 2, maxPriorityFeePerGasScaler: 0.01 }, [CHAIN_IDs.ZORA]: { maxFeePerGasScaler: 2, maxPriorityFeePerGasScaler: 0.01 }, }; @@ -284,6 +293,7 @@ export const multicall3Addresses = { [CHAIN_IDs.OPTIMISM]: "0xcA11bde05977b3631167028862bE2a173976CA11", [CHAIN_IDs.POLYGON]: "0xcA11bde05977b3631167028862bE2a173976CA11", [CHAIN_IDs.SCROLL]: "0xcA11bde05977b3631167028862bE2a173976CA11", + [CHAIN_IDs.WORLD_CHAIN]: "0xcA11bde05977b3631167028862bE2a173976CA11", [CHAIN_IDs.ZK_SYNC]: "0xF9cda624FBC7e059355ce98a31693d299FACd963", [CHAIN_IDs.ZORA]: "0xcA11bde05977b3631167028862bE2a173976CA11", // Testnet: @@ -311,6 +321,7 @@ export const spokesThatHoldEthAndWeth = [ CHAIN_IDs.OPTIMISM, CHAIN_IDs.REDSTONE, CHAIN_IDs.SCROLL, + CHAIN_IDs.WORLD_CHAIN, CHAIN_IDs.ZK_SYNC, CHAIN_IDs.ZORA, ]; @@ -346,6 +357,7 @@ export const SUPPORTED_TOKENS: { [chainId: number]: string[] } = { [CHAIN_IDs.POLYGON]: ["USDC", "USDT", "WETH", "DAI", "WBTC", "UMA", "BAL", "ACX", "POOL"], [CHAIN_IDs.REDSTONE]: ["WETH"], [CHAIN_IDs.SCROLL]: ["WETH", "USDC", "USDT", "WBTC"], + [CHAIN_IDs.WORLD_CHAIN]: ["WETH", "WBTC"], // xxx @todo add USDC after new bridge adapter is supported [CHAIN_IDs.ZK_SYNC]: ["USDC", "USDT", "WETH", "WBTC", "DAI"], [CHAIN_IDs.ZORA]: ["USDC", "WETH"], @@ -398,6 +410,7 @@ export const CANONICAL_BRIDGE: { [CHAIN_IDs.POLYGON]: PolygonERC20Bridge, [CHAIN_IDs.REDSTONE]: OpStackDefaultERC20Bridge, [CHAIN_IDs.SCROLL]: ScrollERC20Bridge, + [CHAIN_IDs.WORLD_CHAIN]: OpStackDefaultERC20Bridge, [CHAIN_IDs.ZK_SYNC]: ZKSyncBridge, [CHAIN_IDs.ZORA]: OpStackDefaultERC20Bridge, }; @@ -444,13 +457,16 @@ export const CUSTOM_BRIDGE: { [TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.MAINNET]]: UsdcTokenSplitterBridge, [TOKEN_SYMBOLS_MAP.WETH.addresses[CHAIN_IDs.MAINNET]]: OpStackWethBridge, }, - [CHAIN_IDs.REDSTONE]: { - [TOKEN_SYMBOLS_MAP.WETH.addresses[CHAIN_IDs.MAINNET]]: OpStackWethBridge, - }, [CHAIN_IDs.POLYGON]: { [TOKEN_SYMBOLS_MAP.WETH.addresses[CHAIN_IDs.MAINNET]]: PolygonWethBridge, [TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.MAINNET]]: UsdcTokenSplitterBridge, }, + [CHAIN_IDs.REDSTONE]: { + [TOKEN_SYMBOLS_MAP.WETH.addresses[CHAIN_IDs.MAINNET]]: OpStackWethBridge, + }, + [CHAIN_IDs.WORLD_CHAIN]: { + [TOKEN_SYMBOLS_MAP.WETH.addresses[CHAIN_IDs.MAINNET]]: OpStackWethBridge, + }, [CHAIN_IDs.ZK_SYNC]: { [TOKEN_SYMBOLS_MAP.WETH.addresses[CHAIN_IDs.MAINNET]]: ZKSyncWethBridge, }, @@ -515,6 +531,7 @@ export const EXPECTED_L1_TO_L2_MESSAGE_TIME = { [CHAIN_IDs.POLYGON]: 60 * 60, [CHAIN_IDs.REDSTONE]: 20 * 60, [CHAIN_IDs.SCROLL]: 60 * 60, + [CHAIN_IDs.WORLD_CHAIN]: 20 * 60, [CHAIN_IDs.ZK_SYNC]: 60 * 60, [CHAIN_IDs.ZORA]: 20 * 60, }; @@ -569,6 +586,21 @@ export const OPSTACK_CONTRACT_OVERRIDES = { }, l2: DEFAULT_L2_CONTRACT_ADDRESSES, }, + [CHAIN_IDs.WORLD_CHAIN]: { + l1: { + AddressManager: "0x5891090d5085679714cb0e62f74950a3c19146a8", + L1CrossDomainMessenger: "0xf931a81D18B1766d15695ffc7c1920a62b7e710a", + L1StandardBridge: CONTRACT_ADDRESSES[CHAIN_IDs.MAINNET].ovmStandardBridge_480.address, + StateCommitmentChain: ZERO_ADDRESS, + CanonicalTransactionChain: ZERO_ADDRESS, + BondManager: ZERO_ADDRESS, + OptimismPortal: "0xd5ec14a83B7d95BE1E2Ac12523e2dEE12Cbeea6C", + L2OutputOracle: "0x19A6d1E9034596196295CF148509796978343c5D", + OptimismPortal2: ZERO_ADDRESS, + DisputeGameFactory: ZERO_ADDRESS, + }, + l2: DEFAULT_L2_CONTRACT_ADDRESSES, + }, }; export const DEFAULT_GAS_MULTIPLIER: { [chainId: number]: number } = { @@ -577,6 +609,7 @@ export const DEFAULT_GAS_MULTIPLIER: { [chainId: number]: number } = { [CHAIN_IDs.LISK]: 1.5, [CHAIN_IDs.MODE]: 1.5, [CHAIN_IDs.REDSTONE]: 1.5, + [CHAIN_IDs.WORLD_CHAIN]: 1.5, [CHAIN_IDs.ZORA]: 1.5, }; diff --git a/src/common/ContractAddresses.ts b/src/common/ContractAddresses.ts index 59a5defb0..a82e1e582 100644 --- a/src/common/ContractAddresses.ts +++ b/src/common/ContractAddresses.ts @@ -73,7 +73,7 @@ export const CONTRACT_ADDRESSES: { // OVM, ZkSync, Linea, and Polygon can't deposit WETH directly so we use an atomic depositor contract that unwraps WETH and // bridges ETH other the canonical bridge. atomicDepositor: { - address: "0xE48278aD2b9b402A8E3C2E0ffbaD7EEe3905bf94", + address: "0xa679201903847f3723Dc88CA7530c8B665bC51a5", abi: ATOMIC_DEPOSITOR_ABI, }, // Since there are multiple ovmStandardBridges on mainnet for different OP Stack chains, we append the chain id of the Op @@ -82,6 +82,10 @@ export const CONTRACT_ADDRESSES: { address: "0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1", abi: OVM_L1_STANDARD_BRIDGE_ABI, }, + ovmStandardBridge_480: { + address: "0x470458C91978D2d929704489Ad730DC3E3001113", + abi: OVM_L1_STANDARD_BRIDGE_ABI, + }, ovmStandardBridge_690: { address: "0xc473ca7E02af24c129c2eEf51F2aDf0411c1Df69", abi: OVM_L1_STANDARD_BRIDGE_ABI, @@ -225,6 +229,15 @@ export const CONTRACT_ADDRESSES: { abi: WETH_ABI, }, }, + 480: { + ovmStandardBridge: { + address: "0x4200000000000000000000000000000000000010", + abi: OVM_L2_STANDARD_BRIDGE_ABI, + }, + eth: { + address: "0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000", + }, + }, 690: { ovmStandardBridge: { address: "0x4200000000000000000000000000000000000010", diff --git a/src/relayer/Relayer.ts b/src/relayer/Relayer.ts index 5ce2aadea..c2c29b43b 100644 --- a/src/relayer/Relayer.ts +++ b/src/relayer/Relayer.ts @@ -19,6 +19,7 @@ import { winston, fixedPointAdjustment, TransactionResponse, + ZERO_ADDRESS, } from "../utils"; import { RelayerClients } from "./RelayerClientHelper"; import { RelayerConfig } from "./RelayerConfig"; @@ -283,7 +284,11 @@ export class Relayer { return false; } - if (deposit.exclusivityDeadline > currentTime && getAddress(deposit.exclusiveRelayer) !== this.relayerAddress) { + if ( + deposit.exclusiveRelayer !== ZERO_ADDRESS && + deposit.exclusivityDeadline > currentTime && + getAddress(deposit.exclusiveRelayer) !== this.relayerAddress + ) { return false; } diff --git a/test/Dataworker.loadData.slowFill.ts b/test/Dataworker.loadData.slowFill.ts index d299216e8..8ae55d4f0 100644 --- a/test/Dataworker.loadData.slowFill.ts +++ b/test/Dataworker.loadData.slowFill.ts @@ -321,6 +321,8 @@ describe("BundleDataClient: Slow fill handling & validation", async function () const destinationChainDeposit = spokePoolClient_2.getDeposits()[0]; // Generate slow fill requests for the slow fill-eligible deposits + await spokePool_1.setCurrentTime(depositsWithSlowFillRequests[1].exclusivityDeadline + 1); // Temporary workaround + await spokePool_2.setCurrentTime(depositsWithSlowFillRequests[0].exclusivityDeadline + 1); // Temporary workaround await requestSlowFill(spokePool_2, relayer, depositsWithSlowFillRequests[0]); await requestSlowFill(spokePool_1, relayer, depositsWithSlowFillRequests[1]); const lastDestinationChainSlowFillRequestBlock = await spokePool_2.provider.getBlockNumber(); diff --git a/test/Relayer.BasicFill.ts b/test/Relayer.BasicFill.ts index 731796c46..19cb1b314 100644 --- a/test/Relayer.BasicFill.ts +++ b/test/Relayer.BasicFill.ts @@ -420,8 +420,7 @@ describe("Relayer: Check for Unfilled Deposits and Fill", async function () { }); it("Ignores exclusive deposits", async function () { - const currentTime = (await spokePool_2.getCurrentTime()).toNumber(); - const exclusivityDeadline = currentTime + 7200; + const exclusivityDeadline = 7200; const deposits: Deposit[] = []; const { fillStatus, relayerAddress } = relayerInstance; @@ -456,7 +455,9 @@ describe("Relayer: Check for Unfilled Deposits and Fill", async function () { expect((await txnReceipts[destinationChainId]).length).to.equal(0); expect(lastSpyLogIncludes(spy, "0 unfilled deposits found")).to.be.true; - await spokePool_2.setCurrentTime(exclusivityDeadline + 1); + const exclusiveDeposit = deposits.find(({ exclusiveRelayer }) => exclusiveRelayer !== relayerAddress); + expect(exclusiveDeposit).to.exist; + await spokePool_2.setCurrentTime(exclusiveDeposit!.exclusivityDeadline + 1); await updateAllClients(); // Relayer can unconditionally fill after the exclusivityDeadline. @@ -952,6 +953,7 @@ describe("Relayer: Check for Unfilled Deposits and Fill", async function () { spy.getCalls().find(({ lastArg }) => lastArg.message.includes("Skipping fill for deposit with message")) ).to.not.be.undefined; } else { + await spokePool_2.setCurrentTime(deposit.exclusivityDeadline + 1); // Temporary workaround. // Now speed up deposit again with a higher fee and a message of 0x. This should be filled. expect((await txnReceipts[destinationChainId]).length).to.equal(1); expect(lastSpyLogIncludes(spy, "Filled v3 deposit")).to.be.true; @@ -1025,6 +1027,7 @@ describe("Relayer: Check for Unfilled Deposits and Fill", async function () { depositor ); + await spokePool_2.setCurrentTime(deposit.exclusivityDeadline + 1); // Temporary workaround. await updateAllClients(); txnReceipts = await relayerInstance.checkForUnfilledDepositsAndFill(); expect((await txnReceipts[destinationChainId]).length).to.equal(1); diff --git a/test/Relayer.SlowFill.ts b/test/Relayer.SlowFill.ts index 008559a1b..15e4d305a 100644 --- a/test/Relayer.SlowFill.ts +++ b/test/Relayer.SlowFill.ts @@ -209,6 +209,7 @@ describe("Relayer: Initiates slow fill requests", async function () { ); expect(deposit).to.exist; + await spokePool_2.setCurrentTime(deposit.exclusivityDeadline + 1); // Temporary workaround await updateAllClients(); const _txnReceipts = await relayerInstance.checkForUnfilledDepositsAndFill(); const txnHashes = await _txnReceipts[destinationChainId]; diff --git a/yarn.lock b/yarn.lock index dfd213345..df0f1b08a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11,15 +11,10 @@ "@uma/common" "^2.17.0" hardhat "^2.9.3" -"@across-protocol/constants@^3.1.13": - version "3.1.13" - resolved "https://registry.yarnpkg.com/@across-protocol/constants/-/constants-3.1.13.tgz#b4caf494e9d9fe50290cca91b7883ea408fdb90a" - integrity sha512-EsTJgQL5p+XXs40aBxOSbMOpQr/f4ty+Iyget8Oh6MT/cncCa2+W8a78fbqYqTtSpH6Sm7E8nvT8gPuSS6ef1w== - -"@across-protocol/constants@^3.1.14": - version "3.1.14" - resolved "https://registry.yarnpkg.com/@across-protocol/constants/-/constants-3.1.14.tgz#03b0e8b1104d5ec6559cdb8c25186cb365c67cba" - integrity sha512-RhtuHCai2GZTRYEeMqsOK4yoIZZGfhUgCxhrY4Fo26tkEOBL+qf/Rjgw9THZHtlqNuGGFIeR4VyxS8GmgxjyZQ== +"@across-protocol/constants@^3.1.16": + version "3.1.16" + resolved "https://registry.yarnpkg.com/@across-protocol/constants/-/constants-3.1.16.tgz#c126085d29d4d051fd02a04c833d804d37c3c219" + integrity sha512-+U+AecGWnfY4b4sSfKBvsDj/+yXKEqpTXcZgI8GVVmUTkUhs1efA0kN4q3q10yy5TXI5TtagaG7R9yZg1zgKKg== "@across-protocol/contracts@^0.1.4": version "0.1.4" @@ -30,12 +25,12 @@ "@openzeppelin/contracts" "4.1.0" "@uma/core" "^2.18.0" -"@across-protocol/contracts@^3.0.10": - version "3.0.10" - resolved "https://registry.yarnpkg.com/@across-protocol/contracts/-/contracts-3.0.10.tgz#965baa824b53af09cd4fb755dadf23776214ef77" - integrity sha512-qZBIkvuU1faZYUj0qFTWN7DVHfkEFK4jn7u5SMHBtAFEtbW2kSIREbE8afWPbhXa5Zah409nQINzYkcfo/I5rw== +"@across-protocol/contracts@^3.0.11": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@across-protocol/contracts/-/contracts-3.0.11.tgz#d010e2a1a44a7ac8184848a54bb9c7b2d41875b0" + integrity sha512-T2C8jOetkcqFDbp8fqI894Dd9qm7D9X7h1kqsI7rYu9paXdaqAUVSR/XcMTq2aHhNAVgb0OlKY/do982ujd0xw== dependencies: - "@across-protocol/constants" "^3.1.13" + "@across-protocol/constants" "^3.1.16" "@defi-wonderland/smock" "^2.3.4" "@eth-optimism/contracts" "^0.5.40" "@ethersproject/abstract-provider" "5.7.0" @@ -47,17 +42,17 @@ "@uma/common" "^2.34.0" "@uma/contracts-node" "^0.4.17" "@uma/core" "^2.56.0" - axios "^1.6.2" + axios "^1.7.4" zksync-web3 "^0.14.3" -"@across-protocol/sdk@^3.2.4": - version "3.2.4" - resolved "https://registry.yarnpkg.com/@across-protocol/sdk/-/sdk-3.2.4.tgz#3c7b9dac1c289ca6161c61358f3efb56e97d8d49" - integrity sha512-3/BzwgQdsWv4MsFsmj5OsmjV66QHHBfAuefPOA/TmPK9PC6CAgpNZNuNmp17Kk5pgagy3UDwBF7EDvWLY+aOhQ== +"@across-protocol/sdk@^3.2.6": + version "3.2.6" + resolved "https://registry.yarnpkg.com/@across-protocol/sdk/-/sdk-3.2.6.tgz#3b3158d2b38d968829b6030ca1d75b53f8e31556" + integrity sha512-ANMQg8WN52WXUqk8NK/abKkze/b5b25Hbe//NhCCzxbsy41W0jaq7fPtwq5gllXc8wHeu+Uvb45WPqM89ByLCw== dependencies: "@across-protocol/across-token" "^1.0.0" - "@across-protocol/constants" "^3.1.14" - "@across-protocol/contracts" "^3.0.10" + "@across-protocol/constants" "^3.1.16" + "@across-protocol/contracts" "^3.0.11" "@eth-optimism/sdk" "^3.3.1" "@ethersproject/bignumber" "^5.7.0" "@pinata/sdk" "^2.1.0" @@ -4059,7 +4054,7 @@ axios@^0.27.2: follow-redirects "^1.14.9" form-data "^4.0.0" -axios@^1.6.2, axios@^1.7.4: +axios@^1.7.4: version "1.7.4" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.4.tgz#4c8ded1b43683c8dd362973c393f3ede24052aa2" integrity sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw== From 97b7ee04df0d4cbb4fb2d88d0689a36e7bb43f78 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Thu, 10 Oct 2024 18:03:06 +0200 Subject: [PATCH 10/14] feat: Support finalizing on World Chain (#1859) This should probably have been part of the larger commit to support World Chain. It has been tested locally and successfully submitted a proof for a WBTC withdrawal. --- src/finalizer/index.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/finalizer/index.ts b/src/finalizer/index.ts index 4cedb298f..ceb9f9102 100644 --- a/src/finalizer/index.ts +++ b/src/finalizer/index.ts @@ -102,6 +102,10 @@ const chainFinalizers: { [chainId: number]: { finalizeOnL2: ChainFinalizer[]; fi finalizeOnL1: [opStackFinalizer], finalizeOnL2: [], }, + [CHAIN_IDs.WORLD_CHAIN]: { + finalizeOnL1: [opStackFinalizer], + finalizeOnL2: [], + }, // Testnets [CHAIN_IDs.BASE_SEPOLIA]: { finalizeOnL1: [cctpL2toL1Finalizer], From d794b4b369edf8ea65fbc342946ee933d8ca8d8e Mon Sep 17 00:00:00 2001 From: bmzig <57361391+bmzig@users.noreply.github.com> Date: Fri, 11 Oct 2024 02:10:02 -0500 Subject: [PATCH 11/14] fix: force maximum USDC rebalance amount over CCTP to 1M (#1860) This is a simple fix to guarantee that the rebalancer will not try to send an amount over CCTP which is greater than 1 million USDC, however, if we needed to send over 1 million USDC, this fix would split the transfers into multiple runs. There might be a follow-up to permit multiple rebalances per run, but this is OK for now. Signed-off-by: bennett --- src/adapter/bridges/UsdcCCTPBridge.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/adapter/bridges/UsdcCCTPBridge.ts b/src/adapter/bridges/UsdcCCTPBridge.ts index c26f4e282..1186805e2 100644 --- a/src/adapter/bridges/UsdcCCTPBridge.ts +++ b/src/adapter/bridges/UsdcCCTPBridge.ts @@ -1,11 +1,21 @@ import { Contract, Signer } from "ethers"; import { CONTRACT_ADDRESSES, chainIdsToCctpDomains } from "../../common"; import { BridgeTransactionDetails, BaseBridgeAdapter, BridgeEvents } from "./BaseBridgeAdapter"; -import { BigNumber, EventSearchConfig, Provider, TOKEN_SYMBOLS_MAP, compareAddressesSimple, assert } from "../../utils"; +import { + BigNumber, + EventSearchConfig, + Provider, + TOKEN_SYMBOLS_MAP, + compareAddressesSimple, + assert, + toBN, +} from "../../utils"; import { processEvent } from "../utils"; import { cctpAddressToBytes32, retrieveOutstandingCCTPBridgeUSDCTransfers } from "../../utils/CCTPUtils"; export class UsdcCCTPBridge extends BaseBridgeAdapter { + private CCTP_MAX_SEND_AMOUNT = toBN(1_000_000_000_000); // 1MM USDC. + constructor(l2chainId: number, hubChainId: number, l1Signer: Signer, l2SignerOrProvider: Signer | Provider) { super(l2chainId, hubChainId, l1Signer, l2SignerOrProvider, [ CONTRACT_ADDRESSES[hubChainId].cctpTokenMessenger.address, @@ -38,6 +48,7 @@ export class UsdcCCTPBridge extends BaseBridgeAdapter { amount: BigNumber ): Promise { assert(compareAddressesSimple(_l1Token, TOKEN_SYMBOLS_MAP.USDC.addresses[this.hubChainId])); + amount = amount.gt(this.CCTP_MAX_SEND_AMOUNT) ? this.CCTP_MAX_SEND_AMOUNT : amount; return Promise.resolve({ contract: this.getL1Bridge(), method: "depositForBurn", From 4b7a4d7fa5927892deb83612a138987f56ae355a Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Tue, 15 Oct 2024 19:42:35 +0200 Subject: [PATCH 12/14] feat: Support World Chain USDC bridges (#1856) Co-authored-by: bennett --- src/adapter/bridges/OpStackUSDCBridge.ts | 68 ++++++++++++ src/adapter/bridges/index.ts | 1 + src/common/Constants.ts | 4 +- src/common/ContractAddresses.ts | 11 +- src/common/abi/OpStackUSDCBridge.json | 135 +++++++++++++++++++++++ 5 files changed, 217 insertions(+), 2 deletions(-) create mode 100644 src/adapter/bridges/OpStackUSDCBridge.ts create mode 100644 src/common/abi/OpStackUSDCBridge.json diff --git a/src/adapter/bridges/OpStackUSDCBridge.ts b/src/adapter/bridges/OpStackUSDCBridge.ts new file mode 100644 index 000000000..898b268b3 --- /dev/null +++ b/src/adapter/bridges/OpStackUSDCBridge.ts @@ -0,0 +1,68 @@ +import { Contract, BigNumber, paginatedEventQuery, EventSearchConfig, Signer, Provider } from "../../utils"; +import { CONTRACT_ADDRESSES } from "../../common"; +import { BaseBridgeAdapter, BridgeTransactionDetails, BridgeEvents } from "./BaseBridgeAdapter"; +import { processEvent } from "../utils"; + +export class OpStackUSDCBridge extends BaseBridgeAdapter { + private readonly l2Gas = 200000; + + constructor( + l2chainId: number, + hubChainId: number, + l1Signer: Signer, + l2SignerOrProvider: Signer | Provider, + _l1Token: string + ) { + // Lint Appeasement + _l1Token; + const { address: l1Address, abi: l1Abi } = CONTRACT_ADDRESSES[hubChainId][`opUSDCBridge_${l2chainId}`]; + const { address: l2Address, abi: l2Abi } = CONTRACT_ADDRESSES[l2chainId].opUSDCBridge; + super(l2chainId, hubChainId, l1Signer, l2SignerOrProvider, [l1Address]); + + this.l1Bridge = new Contract(l1Address, l1Abi, l1Signer); + this.l2Bridge = new Contract(l2Address, l2Abi, l2SignerOrProvider); + } + + async constructL1ToL2Txn( + toAddress: string, + _l1Token: string, + _l2Token: string, + amount: BigNumber + ): Promise { + return Promise.resolve({ + contract: this.getL1Bridge(), + method: "sendMessage", + args: [toAddress, amount, this.l2Gas], + }); + } + + async queryL1BridgeInitiationEvents( + l1Token: string, + _fromAddress: string, + toAddress: string, + eventConfig: EventSearchConfig + ): Promise { + const l1Bridge = this.getL1Bridge(); + const events = await paginatedEventQuery(l1Bridge, l1Bridge.filters.MessageSent(undefined, toAddress), eventConfig); + return { + [this.resolveL2TokenAddress(l1Token)]: events.map((event) => processEvent(event, "_amount", "_to", "_user")), + }; + } + + async queryL2BridgeFinalizationEvents( + l1Token: string, + _fromAddress: string, + toAddress: string, + eventConfig: EventSearchConfig + ): Promise { + const l2Bridge = this.getL2Bridge(); + const events = await paginatedEventQuery( + l2Bridge, + l2Bridge.filters.MessageReceived(undefined, toAddress), + eventConfig + ); + return { + [this.resolveL2TokenAddress(l1Token)]: events.map((event) => processEvent(event, "_amount", "_user", "_spender")), + }; + } +} diff --git a/src/adapter/bridges/index.ts b/src/adapter/bridges/index.ts index e05a0058a..ef672f619 100644 --- a/src/adapter/bridges/index.ts +++ b/src/adapter/bridges/index.ts @@ -14,3 +14,4 @@ export * from "./ZKSyncWethBridge"; export * from "./LineaWethBridge"; export * from "./BlastBridge"; export * from "./ScrollERC20Bridge"; +export * from "./OpStackUSDCBridge"; diff --git a/src/common/Constants.ts b/src/common/Constants.ts index ae817a340..2cb9f579e 100644 --- a/src/common/Constants.ts +++ b/src/common/Constants.ts @@ -16,6 +16,7 @@ import { LineaWethBridge, BlastBridge, ScrollERC20Bridge, + OpStackUSDCBridge, } from "../adapter/bridges"; import { DEFAULT_L2_CONTRACT_ADDRESSES } from "@eth-optimism/sdk"; import { CONTRACT_ADDRESSES } from "./ContractAddresses"; @@ -357,7 +358,7 @@ export const SUPPORTED_TOKENS: { [chainId: number]: string[] } = { [CHAIN_IDs.POLYGON]: ["USDC", "USDT", "WETH", "DAI", "WBTC", "UMA", "BAL", "ACX", "POOL"], [CHAIN_IDs.REDSTONE]: ["WETH"], [CHAIN_IDs.SCROLL]: ["WETH", "USDC", "USDT", "WBTC"], - [CHAIN_IDs.WORLD_CHAIN]: ["WETH", "WBTC"], // xxx @todo add USDC after new bridge adapter is supported + [CHAIN_IDs.WORLD_CHAIN]: ["WETH", "WBTC", "USDC"], [CHAIN_IDs.ZK_SYNC]: ["USDC", "USDT", "WETH", "WBTC", "DAI"], [CHAIN_IDs.ZORA]: ["USDC", "WETH"], @@ -465,6 +466,7 @@ export const CUSTOM_BRIDGE: { [TOKEN_SYMBOLS_MAP.WETH.addresses[CHAIN_IDs.MAINNET]]: OpStackWethBridge, }, [CHAIN_IDs.WORLD_CHAIN]: { + [TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.MAINNET]]: OpStackUSDCBridge, [TOKEN_SYMBOLS_MAP.WETH.addresses[CHAIN_IDs.MAINNET]]: OpStackWethBridge, }, [CHAIN_IDs.ZK_SYNC]: { diff --git a/src/common/ContractAddresses.ts b/src/common/ContractAddresses.ts index a82e1e582..4433ed226 100644 --- a/src/common/ContractAddresses.ts +++ b/src/common/ContractAddresses.ts @@ -5,8 +5,9 @@ import ATOMIC_DEPOSITOR_ABI from "./abi/AtomicDepositor.json"; import WETH_ABI from "./abi/Weth.json"; import HUB_POOL_ABI from "./abi/HubPool.json"; import VOTING_V2_ABI from "./abi/VotingV2.json"; -import OVM_L2_STANDARD_BRIDGE_ABI from "./abi/OpStackStandardBridgeL2.json"; +import OP_USDC_BRIDGE_ABI from "./abi/OpStackUSDCBridge.json"; import OVM_L1_STANDARD_BRIDGE_ABI from "./abi/OpStackStandardBridgeL1.json"; +import OVM_L2_STANDARD_BRIDGE_ABI from "./abi/OpStackStandardBridgeL2.json"; import SNX_OPTIMISM_BRIDGE_L1_ABI from "./abi/SnxOptimismBridgeL1.json"; import SNX_OPTIMISM_BRIDGE_L2_ABI from "./abi/SnxOptimismBridgeL2.json"; import DAI_OPTIMISM_BRIDGE_L1_ABI from "./abi/DaiOptimismBridgeL1.json"; @@ -76,6 +77,10 @@ export const CONTRACT_ADDRESSES: { address: "0xa679201903847f3723Dc88CA7530c8B665bC51a5", abi: ATOMIC_DEPOSITOR_ABI, }, + opUSDCBridge_480: { + address: "0x153A69e4bb6fEDBbAaF463CB982416316c84B2dB", + abi: OP_USDC_BRIDGE_ABI, + }, // Since there are multiple ovmStandardBridges on mainnet for different OP Stack chains, we append the chain id of the Op // Stack chain to the name to differentiate. This one is for Optimism. ovmStandardBridge_10: { @@ -230,6 +235,10 @@ export const CONTRACT_ADDRESSES: { }, }, 480: { + opUSDCBridge: { + address: "0xbD80b06d3dbD0801132c6689429aC09Ca6D27f82", + abi: OP_USDC_BRIDGE_ABI, + }, ovmStandardBridge: { address: "0x4200000000000000000000000000000000000010", abi: OVM_L2_STANDARD_BRIDGE_ABI, diff --git a/src/common/abi/OpStackUSDCBridge.json b/src/common/abi/OpStackUSDCBridge.json new file mode 100644 index 000000000..3a4b049f6 --- /dev/null +++ b/src/common/abi/OpStackUSDCBridge.json @@ -0,0 +1,135 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amountWithdrawn", + "type": "uint256" + } + ], + "name": "LockedFundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "_messenger", + "type": "address" + } + ], + "name": "MessageReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "_messenger", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32" + } + ], + "name": "MessageSent", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "receiveMessage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32" + } + ], + "name": "sendMessage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] From dd3a69d04c5c9b0d7c642a642286c5491d306592 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Wed, 16 Oct 2024 10:02:01 +0200 Subject: [PATCH 13/14] chore: Bump SDK (#1863) This includes an optimisation for the SpokePoolClient to bundle two separate SpokePool calls into a SpokePool multicall. Ideally this will reduce the instance of RPC errors when this query occurs against a block that's slightly ahead of one of the RPC providers. --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 3861c1f95..9bf8842b7 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "dependencies": { "@across-protocol/constants": "^3.1.16", "@across-protocol/contracts": "^3.0.11", - "@across-protocol/sdk": "^3.2.6", + "@across-protocol/sdk": "^3.2.7", "@arbitrum/sdk": "^3.1.3", "@consensys/linea-sdk": "^0.2.1", "@defi-wonderland/smock": "^2.3.5", diff --git a/yarn.lock b/yarn.lock index df0f1b08a..045e6f404 100644 --- a/yarn.lock +++ b/yarn.lock @@ -45,10 +45,10 @@ axios "^1.7.4" zksync-web3 "^0.14.3" -"@across-protocol/sdk@^3.2.6": - version "3.2.6" - resolved "https://registry.yarnpkg.com/@across-protocol/sdk/-/sdk-3.2.6.tgz#3b3158d2b38d968829b6030ca1d75b53f8e31556" - integrity sha512-ANMQg8WN52WXUqk8NK/abKkze/b5b25Hbe//NhCCzxbsy41W0jaq7fPtwq5gllXc8wHeu+Uvb45WPqM89ByLCw== +"@across-protocol/sdk@^3.2.7": + version "3.2.7" + resolved "https://registry.yarnpkg.com/@across-protocol/sdk/-/sdk-3.2.7.tgz#c0d2ad49065a33d05f01f846e328989c4e6585c2" + integrity sha512-oUZ8uIw10/y+ZsRjlZTivJnK3AGpwCJbt3VLMHhv6TUYGNcQW/Vr71LFhyeieKfoY4+lGZq/UV4QIqsNSWiSZA== dependencies: "@across-protocol/across-token" "^1.0.0" "@across-protocol/constants" "^3.1.16" From bd9bde439dd764adca0b0dd62688d2913503e3b2 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Wed, 16 Oct 2024 10:54:13 +0200 Subject: [PATCH 14/14] chore: Bump viem (#1858) To gain the recently-added worldchain definitions. --- package.json | 2 +- src/libexec/SpokePoolListenerExperimental.ts | 1 + yarn.lock | 106 ++++++++----------- 3 files changed, 48 insertions(+), 61 deletions(-) diff --git a/package.json b/package.json index 9bf8842b7..6d074695c 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "redis4": "npm:redis@^4.1.0", "superstruct": "^1.0.3", "ts-node": "^10.9.1", - "viem": "^2.21.7", + "viem": "^2.21.18", "winston": "^3.10.0", "zksync-ethers": "^5.7.2" }, diff --git a/src/libexec/SpokePoolListenerExperimental.ts b/src/libexec/SpokePoolListenerExperimental.ts index e5e2b5d31..5236575c7 100644 --- a/src/libexec/SpokePoolListenerExperimental.ts +++ b/src/libexec/SpokePoolListenerExperimental.ts @@ -49,6 +49,7 @@ const _chains = { [CHAIN_IDs.POLYGON]: chains.polygon, [CHAIN_IDs.REDSTONE]: chains.redstone, [CHAIN_IDs.SCROLL]: chains.scroll, + [CHAIN_IDs.WORLD_CHAIN]: chains.worldchain, [CHAIN_IDs.ZK_SYNC]: chains.zksync, [CHAIN_IDs.ZORA]: chains.zora, } as const; diff --git a/yarn.lock b/yarn.lock index 045e6f404..effb7bb56 100644 --- a/yarn.lock +++ b/yarn.lock @@ -69,10 +69,10 @@ superstruct "^0.15.4" tslib "^2.6.2" -"@adraffy/ens-normalize@1.10.0": - version "1.10.0" - resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" - integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== +"@adraffy/ens-normalize@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz#42cc67c5baa407ac25059fcd7d405cc5ecdb0c33" + integrity sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg== "@arbitrum/sdk@^3.1.3": version "3.1.3" @@ -1503,37 +1503,18 @@ resolved "https://registry.yarnpkg.com/@multiformats/base-x/-/base-x-4.0.1.tgz#95ff0fa58711789d53aefb2590a8b7a4e715d121" integrity sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw== -"@noble/curves@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.0.tgz#f05771ef64da724997f69ee1261b2417a49522d6" - integrity sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg== - dependencies: - "@noble/hashes" "1.4.0" - -"@noble/curves@^1.4.0": +"@noble/curves@1.6.0", "@noble/curves@^1.4.0", "@noble/curves@~1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.6.0.tgz#be5296ebcd5a1730fccea4786d420f87abfeb40b" integrity sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ== dependencies: "@noble/hashes" "1.5.0" -"@noble/curves@~1.4.0": - version "1.4.2" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" - integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== - dependencies: - "@noble/hashes" "1.4.0" - "@noble/hashes@1.0.0", "@noble/hashes@~1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.0.0.tgz#d5e38bfbdaba174805a4e649f13be9a9ed3351ae" integrity sha512-DZVbtY62kc3kkBtMHqwCOfXrT/hnoORy5BJ4+HU1IR59X0KWAOqsfzQPcUl/lQLlG7qXbe/fZ3r/emxtAl+sqg== -"@noble/hashes@1.4.0", "@noble/hashes@~1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" - integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== - "@noble/hashes@1.5.0", "@noble/hashes@^1.4.0", "@noble/hashes@~1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.5.0.tgz#abadc5ca20332db2b1b2aa3e496e9af1213570b0" @@ -2404,7 +2385,12 @@ resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.0.0.tgz#109fb595021de285f05a7db6806f2f48296fcee7" integrity sha512-gIVaYhUsy+9s58m/ETjSJVKHhKTBMmcRb9cEV5/5dwvfDlfORjKrFsDeDHWRrm6RjcPvCLZFwGJjAjLj1gg4HA== -"@scure/base@~1.1.6", "@scure/base@~1.1.8": +"@scure/base@~1.1.7": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1" + integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg== + +"@scure/base@~1.1.8": version "1.1.8" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.8.tgz#8f23646c352f020c83bca750a82789e246d42b50" integrity sha512-6CyAclxj3Nb0XT7GHK6K4zK6k2xJm6E4Ft0Ohjt4WgegiFUHEtFb2CGzmPmGBwoIhrLsqNLYfLr04Y1GePrzZg== @@ -2418,14 +2404,14 @@ "@noble/secp256k1" "~1.5.2" "@scure/base" "~1.0.0" -"@scure/bip32@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.4.0.tgz#4e1f1e196abedcef395b33b9674a042524e20d67" - integrity sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg== +"@scure/bip32@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.5.0.tgz#dd4a2e1b8a9da60e012e776d954c4186db6328e6" + integrity sha512-8EnFYkqEQdnkuGBVpCzKxyIwDCBLDVj3oiX0EKUFre/tOjL/Hqba1D6n/8RcmaQy4f95qQFrO2A8Sr6ybh4NRw== dependencies: - "@noble/curves" "~1.4.0" - "@noble/hashes" "~1.4.0" - "@scure/base" "~1.1.6" + "@noble/curves" "~1.6.0" + "@noble/hashes" "~1.5.0" + "@scure/base" "~1.1.7" "@scure/bip39@1.0.0": version "1.0.0" @@ -3467,10 +3453,10 @@ abbrev@1.0.x: web3-eth-abi "^1.2.1" web3-utils "^1.2.1" -abitype@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.5.tgz#29d0daa3eea867ca90f7e4123144c1d1270774b6" - integrity sha512-YzDhti7cjlfaBhHutMaboYB21Ha3rXR9QTkNJFzYC4kC8YclaiwPBBBJY8ejFdu2wnJeZCVZSMlQJ7fi8S6hsw== +abitype@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.6.tgz#76410903e1d88e34f1362746e2d407513c38565b" + integrity sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A== abort-controller@^3.0.0: version "3.0.0" @@ -9088,10 +9074,10 @@ isomorphic-unfetch@^3.0.0: node-fetch "^2.6.1" unfetch "^4.2.0" -isows@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.4.tgz#810cd0d90cc4995c26395d2aa4cfa4037ebdf061" - integrity sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ== +isows@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.6.tgz#0da29d706fa51551c663c627ace42769850f86e7" + integrity sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw== isstream@~0.1.2: version "0.1.2" @@ -14705,20 +14691,20 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -viem@^2.21.7: - version "2.21.7" - resolved "https://registry.yarnpkg.com/viem/-/viem-2.21.7.tgz#c933fd3adb6f771e5c5fe2b4d7a14d8701ddc32f" - integrity sha512-PFgppakInuHX31wHDx1dzAjhj4t6Po6WrWtutDi33z2vabIT0Wv8qT6tl7DLqfLy2NkTqfN2mdshYLeoI5ZHvQ== +viem@^2.21.18: + version "2.21.21" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.21.21.tgz#11a5001fa18c8a47548a4b20ae9ddd8cfb14de3f" + integrity sha512-KJPqpAXy8kyZQICx1nURUXqd8aABP9RweAZhfp27MzMPsAAxP450cWPlEffEAUrvsyyj5edVbIcHESE8DYVzFA== dependencies: - "@adraffy/ens-normalize" "1.10.0" - "@noble/curves" "1.4.0" - "@noble/hashes" "1.4.0" - "@scure/bip32" "1.4.0" + "@adraffy/ens-normalize" "1.11.0" + "@noble/curves" "1.6.0" + "@noble/hashes" "1.5.0" + "@scure/bip32" "1.5.0" "@scure/bip39" "1.4.0" - abitype "1.0.5" - isows "1.0.4" - webauthn-p256 "0.0.5" - ws "8.17.1" + abitype "1.0.6" + isows "1.0.6" + webauthn-p256 "0.0.10" + ws "8.18.0" walk-up-path@^1.0.0: version "1.0.0" @@ -15212,10 +15198,10 @@ web3@1.8.2, web3@^1.6.0: web3-shh "1.8.2" web3-utils "1.8.2" -webauthn-p256@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/webauthn-p256/-/webauthn-p256-0.0.5.tgz#0baebd2ba8a414b21cc09c0d40f9dd0be96a06bd" - integrity sha512-drMGNWKdaixZNobeORVIqq7k5DsRC9FnG201K2QjeOoQLmtSDaSsVZdkg6n5jUALJKcAG++zBPJXmv6hy0nWFg== +webauthn-p256@0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/webauthn-p256/-/webauthn-p256-0.0.10.tgz#877e75abe8348d3e14485932968edf3325fd2fdd" + integrity sha512-EeYD+gmIT80YkSIDb2iWq0lq2zbHo1CxHlQTeJ+KkCILWpVy3zASH3ByD4bopzfk0uCwXxLqKGLqp2W4O28VFA== dependencies: "@noble/curves" "^1.4.0" "@noble/hashes" "^1.4.0" @@ -15442,10 +15428,10 @@ ws@7.4.6: resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== -ws@8.17.1: - version "8.17.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" - integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== +ws@8.18.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== ws@^3.0.0: version "3.3.3"