Skip to content

Commit

Permalink
improve: swap Optimism and Base OpStackAdapters with BaseChainAdapters (
Browse files Browse the repository at this point in the history
#1839)

* improve: swap Optimism and Base OpStackAdapters with BaseChainAdapters

Signed-off-by: bennett <[email protected]>

---------

Signed-off-by: bennett <[email protected]>
  • Loading branch information
bmzig authored Oct 2, 2024
1 parent 560abc0 commit 6b42f79
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 31 deletions.
36 changes: 32 additions & 4 deletions src/adapter/bridges/SnxOptimismBridge.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -43,11 +51,19 @@ export class SnxOptimismBridge extends BaseBridgeAdapter {
toAddress: string,
eventConfig: EventSearchConfig
): Promise<BridgeEvents> {
// @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 {
Expand All @@ -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<boolean> {
return isContractDeployedToAddress(address, this.getL2Bridge().provider);
}
}
20 changes: 13 additions & 7 deletions src/clients/bridges/AdapterManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion src/common/abi/SnxOptimismBridgeL1.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
16 changes: 8 additions & 8 deletions test/AdapterManager.SendTokensCrossChain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
);

Expand All @@ -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
);

Expand Down Expand Up @@ -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
);

Expand All @@ -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
);
});
Expand Down Expand Up @@ -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
);

Expand All @@ -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
);

Expand All @@ -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
);

Expand All @@ -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
);
});
Expand Down
20 changes: 9 additions & 11 deletions test/generic-adapters/OpStack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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 = (
Expand Down

0 comments on commit 6b42f79

Please sign in to comment.