From e4afb1c4077a3b22ed17bf0ad0110c42131147a8 Mon Sep 17 00:00:00 2001 From: Shahul Hameed <10547529+shahthepro@users.noreply.github.com> Date: Tue, 29 Sep 2026 16:33:14 +0800 Subject: [PATCH] Fix Interface usage --- .../IBridgedWOETHMigrationStrategy.sol | 30 +++------ .../interfaces/crosschainV3/IAdapter.sol | 38 +++--------- .../crosschainV3/IRemoteWOTokenStrategy.sol | 62 +++++++------------ .../BridgedWOETHMigrationStrategy.sol | 13 ++-- .../crosschainV3/RemoteWOTokenStrategy.sol | 43 +++---------- .../crosschainV3/adapters/AbstractAdapter.sol | 31 +--------- .../deploy/base/003_OETHbV3MasterImpl.s.sol | 4 +- .../mainnet/007_OETHbV3RemoteImpl.s.sol | 7 +-- .../shared/Shared.t.sol | 24 ++++++- .../RemoteWOTokenStrategy/shared/Shared.t.sol | 12 +++- 10 files changed, 93 insertions(+), 171 deletions(-) diff --git a/contracts/contracts/interfaces/IBridgedWOETHMigrationStrategy.sol b/contracts/contracts/interfaces/IBridgedWOETHMigrationStrategy.sol index 58d15c69fd..99276f55ee 100644 --- a/contracts/contracts/interfaces/IBridgedWOETHMigrationStrategy.sol +++ b/contracts/contracts/interfaces/IBridgedWOETHMigrationStrategy.sol @@ -1,6 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; +/// @dev Inherited by `BridgedWOETHMigrationStrategy`, so it declares only what that contract +/// defines itself. Members from `BridgedWOETHStrategy` / `InitializableAbstractStrategy` / +/// `Governable` (e.g. `weth`, `lastOraclePrice`, `vaultAddress`, `governor`) are public +/// getters or non-virtual functions there and so can't be declared here. `ccipRouter` is +/// omitted because its `IRouterClient`-typed getter can't implement an `address` return. interface IBridgedWOETHMigrationStrategy { // Events event WOETHBridgedToRemote(uint256 amount, uint256 totalBridged); @@ -11,7 +16,9 @@ interface IBridgedWOETHMigrationStrategy { function setMaxPerBridge(uint256 maxPerBridge) external; - // Views (migration) + // Views + function checkBalance(address asset) external view returns (uint256); + function master() external view returns (address); function ccipChainSelectorMainnet() external view returns (uint64); @@ -19,25 +26,4 @@ interface IBridgedWOETHMigrationStrategy { function totalBridged() external view returns (uint256); function maxPerBridge() external view returns (uint256); - - // Views (inherited from BridgedWOETHStrategy) - function checkBalance(address asset) external view returns (uint256); - - function updateWOETHOraclePrice() external returns (uint256); - - function lastOraclePrice() external view returns (uint128); - - function maxPriceDiffBps() external view returns (uint128); - - function weth() external view returns (address); - - function bridgedWOETH() external view returns (address); - - function oethb() external view returns (address); - - function oracle() external view returns (address); - - function vaultAddress() external view returns (address); - - function governor() external view returns (address); } diff --git a/contracts/contracts/interfaces/crosschainV3/IAdapter.sol b/contracts/contracts/interfaces/crosschainV3/IAdapter.sol index 10ee4c0b1f..a0b1e7cf36 100644 --- a/contracts/contracts/interfaces/crosschainV3/IAdapter.sol +++ b/contracts/contracts/interfaces/crosschainV3/IAdapter.sol @@ -1,13 +1,17 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; -interface IAdapter { - /// @dev Per-lane routing config, keyed by the authorised sender strategy. Declared here so - /// tests can build and read it back by field name. +import { IBridgeAdapter } from "./IBridgeAdapter.sol"; + +/// @dev Inherited by `AbstractAdapter`, so it declares only what that contract defines itself. +/// Governance (`governor` / `transferGovernance` / `claimGovernance`) comes from +/// `Governable`, whose functions are not virtual and so can't satisfy an interface. +interface IAdapter is IBridgeAdapter { + /// @notice Per-lane routing config. One row per authorised sender. struct ChainConfig { bool paused; - uint64 chainSelector; - uint32 destGasLimit; + uint64 chainSelector; // destination chain identifier (protocol-specific encoding) + uint32 destGasLimit; // gas hint forwarded to the receive callback on the peer } // Events @@ -65,28 +69,4 @@ interface IAdapter { function authorised(address sender) external view returns (bool); function strategists(address who) external view returns (bool); - - function maxTransferAmount() external view returns (uint256); - - function minTransferAmount() external view returns (uint256); - - function quoteFee( - address token, - uint256 amount, - bytes calldata payload - ) - external - view - returns ( - uint256 fee, - address feeToken, - bool requiresExternalPayment - ); - - // Governance (from Governable) - function transferGovernance(address newGovernor) external; - - function claimGovernance() external; - - function governor() external view returns (address); } diff --git a/contracts/contracts/interfaces/crosschainV3/IRemoteWOTokenStrategy.sol b/contracts/contracts/interfaces/crosschainV3/IRemoteWOTokenStrategy.sol index 0dfe9e0454..504d284728 100644 --- a/contracts/contracts/interfaces/crosschainV3/IRemoteWOTokenStrategy.sol +++ b/contracts/contracts/interfaces/crosschainV3/IRemoteWOTokenStrategy.sol @@ -1,9 +1,23 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; +/// @dev Inherited by `RemoteWOTokenStrategy`, so it declares only what that contract defines +/// itself. Members from its bases (`AbstractCrossChainV3Strategy` adapters / operator / +/// nonce state, `AbstractWOTokenStrategy.bridgeAsset`, `Governable`) are public getters or +/// non-virtual functions there and so can't be declared here. interface IRemoteWOTokenStrategy { - // Events (RemoteWOTokenStrategy) + // Events event DepositProcessed(uint64 nonce, uint256 amount, uint256 remoteBalance); + event WithdrawRequestProcessed( + uint64 nonce, + uint256 amount, + uint256 requestId + ); + event WithdrawClaimDelivered( + uint64 nonce, + uint256 amount, + uint256 remoteBalance + ); event WithdrawClaimNack(uint64 nonce, uint256 remoteBalance); event RemoteWithdrawalClaimed(uint256 requestId, uint256 amount); event BalanceReportSent( @@ -11,15 +25,17 @@ interface IRemoteWOTokenStrategy { uint256 remoteBalance, uint256 timestamp ); + /// @dev DEPOSIT mint/wrap reverted; bridgeAsset/oToken left idle (recoverable via retryDeposit). event DepositUnderlyingFailed(uint64 nonce, uint256 amount, bytes reason); + /// @dev WITHDRAW_REQUEST unwrap/queue reverted; nothing queued, Master told to clear pending. + event WithdrawRequestUnderlyingFailed( + uint64 nonce, + uint256 amount, + bytes reason + ); + /// @dev Operator re-ran the mint/wrap pipeline on idle bridgeAsset/oToken. event IdleDepositRetried(uint256 mintedBridgeAsset, uint256 wrappedOToken); - // Events (AbstractCrossChainV3Strategy) - event YieldNonceAdvanced(uint64 nonce); - event OutboundAdapterUpdated(address oldAdapter, address newAdapter); - event InboundAdapterUpdated(address oldAdapter, address newAdapter); - event OperatorUpdated(address oldOperator, address newOperator); - // Lifecycle function initialize(address operator) external; @@ -32,44 +48,12 @@ interface IRemoteWOTokenStrategy { function claimRemoteWithdrawal() external; - // Inbound - function receiveMessage( - address sender, - address token, - uint256 amountReceived, - bytes calldata payload - ) external; - // Governance - function setOutboundAdapter(address adapter) external; - - function setInboundAdapter(address adapter) external; - - function setOperator(address operator) external; - - function transferNative(uint256 amount) external; - function transferToken(address asset, uint256 amount) external; // Views function checkBalance(address asset) external view returns (uint256); - function isYieldOpInFlight() external view returns (bool); - - function lastYieldNonce() external view returns (uint64); - - function nonceProcessed(uint64 nonce) external view returns (bool); - - function lastBalanceCheckTimestamp() external view returns (uint256); - - function outboundAdapter() external view returns (address); - - function inboundAdapter() external view returns (address); - - function operator() external view returns (address); - - function bridgeAsset() external view returns (address); - function oToken() external view returns (address); function woToken() external view returns (address); diff --git a/contracts/contracts/strategies/BridgedWOETHMigrationStrategy.sol b/contracts/contracts/strategies/BridgedWOETHMigrationStrategy.sol index ed943b1861..2e5e4764c5 100644 --- a/contracts/contracts/strategies/BridgedWOETHMigrationStrategy.sol +++ b/contracts/contracts/strategies/BridgedWOETHMigrationStrategy.sol @@ -9,6 +9,7 @@ import { Client } from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client import { BridgedWOETHStrategy } from "./BridgedWOETHStrategy.sol"; import { IStrategy } from "../interfaces/IStrategy.sol"; +import { IBridgedWOETHMigrationStrategy } from "../interfaces/IBridgedWOETHMigrationStrategy.sol"; import { CCIPMessageBuilder } from "./crosschainV3/libraries/CCIPMessageBuilder.sol"; /** @@ -32,7 +33,10 @@ import { CCIPMessageBuilder } from "./crosschainV3/libraries/CCIPMessageBuilder. * - V1's `setMaxPriceDiffBps` (governor-only) and depositBridgedWOETH / * withdrawBridgedWOETH (governor or strategist) are inherited unchanged. */ -contract BridgedWOETHMigrationStrategy is BridgedWOETHStrategy { +contract BridgedWOETHMigrationStrategy is + BridgedWOETHStrategy, + IBridgedWOETHMigrationStrategy +{ using SafeERC20 for IERC20; // --- Immutables ------------------------------------------------------- @@ -58,11 +62,6 @@ contract BridgedWOETHMigrationStrategy is BridgedWOETHStrategy { uint256[48] private __gap; - // --- Events ----------------------------------------------------------- - - event MaxPerBridgeSet(uint256 maxPerBridge); - event WOETHBridgedToRemote(uint256 amount, uint256 totalBridged); - // --- Errors ----------------------------------------------------------- // (none — using require strings for parity with the rest of the codebase) @@ -192,7 +191,7 @@ contract BridgedWOETHMigrationStrategy is BridgedWOETHStrategy { function checkBalance(address _asset) external view - override + override(BridgedWOETHStrategy, IBridgedWOETHMigrationStrategy) returns (uint256) { require(_asset == address(weth), "BWM: unsupported asset"); diff --git a/contracts/contracts/strategies/crosschainV3/RemoteWOTokenStrategy.sol b/contracts/contracts/strategies/crosschainV3/RemoteWOTokenStrategy.sol index f24a70e956..126f9e8683 100644 --- a/contracts/contracts/strategies/crosschainV3/RemoteWOTokenStrategy.sol +++ b/contracts/contracts/strategies/crosschainV3/RemoteWOTokenStrategy.sol @@ -6,6 +6,7 @@ import { IERC4626 } from "../../../lib/openzeppelin/interfaces/IERC4626.sol"; import { IVault } from "../../interfaces/IVault.sol"; import { IBasicToken } from "../../interfaces/IBasicToken.sol"; import { IBridgeAdapter } from "../../interfaces/crosschainV3/IBridgeAdapter.sol"; +import { IRemoteWOTokenStrategy } from "../../interfaces/crosschainV3/IRemoteWOTokenStrategy.sol"; import { AbstractWOTokenStrategy } from "./AbstractWOTokenStrategy.sol"; import { CrossChainV3Helper } from "./CrossChainV3Helper.sol"; @@ -27,7 +28,10 @@ import { CrossChainV3Helper } from "./CrossChainV3Helper.sol"; * For the full Remote state-transition table (Idle → Requested → Claimed → Bridging-out * → Completed) see `FLOWS.md`. */ -contract RemoteWOTokenStrategy is AbstractWOTokenStrategy { +contract RemoteWOTokenStrategy is + AbstractWOTokenStrategy, + IRemoteWOTokenStrategy +{ using SafeERC20 for IERC20; // --- Immutables -------------------------------------------------------- @@ -63,37 +67,6 @@ contract RemoteWOTokenStrategy is AbstractWOTokenStrategy { /// @dev Reserved for future expansion. uint256[43] private __gap; - // --- Events ------------------------------------------------------------- - - event DepositProcessed(uint64 nonce, uint256 amount, uint256 remoteBalance); - event WithdrawRequestProcessed( - uint64 nonce, - uint256 amount, - uint256 requestId - ); - event WithdrawClaimDelivered( - uint64 nonce, - uint256 amount, - uint256 remoteBalance - ); - event WithdrawClaimNack(uint64 nonce, uint256 remoteBalance); - event RemoteWithdrawalClaimed(uint256 requestId, uint256 amount); - event BalanceReportSent( - uint64 nonce, - uint256 remoteBalance, - uint256 timestamp - ); - /// @dev DEPOSIT mint/wrap reverted; bridgeAsset/oToken left idle (recoverable via retryDeposit). - event DepositUnderlyingFailed(uint64 nonce, uint256 amount, bytes reason); - /// @dev WITHDRAW_REQUEST unwrap/queue reverted; nothing queued, Master told to clear pending. - event WithdrawRequestUnderlyingFailed( - uint64 nonce, - uint256 amount, - bytes reason - ); - /// @dev Operator re-ran the mint/wrap pipeline on idle bridgeAsset/oToken. - event IdleDepositRetried(uint256 mintedBridgeAsset, uint256 wrappedOToken); - // --- Construction / initialisation ------------------------------------- constructor( @@ -140,7 +113,7 @@ contract RemoteWOTokenStrategy is AbstractWOTokenStrategy { function checkBalance(address _asset) external view - override + override(InitializableAbstractStrategy, IRemoteWOTokenStrategy) returns (uint256) { require(_asset == bridgeAsset, "Remote: unsupported asset"); @@ -152,7 +125,7 @@ contract RemoteWOTokenStrategy is AbstractWOTokenStrategy { /// @inheritdoc InitializableAbstractStrategy function safeApproveAllTokens() external - override + override(InitializableAbstractStrategy, IRemoteWOTokenStrategy) onlyGovernor nonReentrant { @@ -205,7 +178,7 @@ contract RemoteWOTokenStrategy is AbstractWOTokenStrategy { /// recoverable; true custody recovery goes through the governor upgrade path. function transferToken(address _asset, uint256 _amount) public - override + override(InitializableAbstractStrategy, IRemoteWOTokenStrategy) onlyGovernor { require( diff --git a/contracts/contracts/strategies/crosschainV3/adapters/AbstractAdapter.sol b/contracts/contracts/strategies/crosschainV3/adapters/AbstractAdapter.sol index 0b3fe2e835..2ae06e5652 100644 --- a/contracts/contracts/strategies/crosschainV3/adapters/AbstractAdapter.sol +++ b/contracts/contracts/strategies/crosschainV3/adapters/AbstractAdapter.sol @@ -5,6 +5,7 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { Governable } from "../../../governance/Governable.sol"; +import { IAdapter } from "../../../interfaces/crosschainV3/IAdapter.sol"; import { IBridgeAdapter } from "../../../interfaces/crosschainV3/IBridgeAdapter.sol"; import { IBridgeReceiver } from "../../../interfaces/crosschainV3/IBridgeReceiver.sol"; @@ -38,16 +39,9 @@ import { IBridgeReceiver } from "../../../interfaces/crosschainV3/IBridgeReceive * Concrete adapters implement three internal hooks for the bridge-specific transport * calls: `_sendMessage`, `_sendMessageAndTokens`, `_quoteFee`. */ -abstract contract AbstractAdapter is IBridgeAdapter, Governable { +abstract contract AbstractAdapter is IAdapter, Governable { using SafeERC20 for IERC20; - /// @notice Per-lane routing config. One row per authorised sender. - struct ChainConfig { - bool paused; - uint64 chainSelector; // destination chain identifier (protocol-specific encoding) - uint32 destGasLimit; // gas hint forwarded to the receive callback on the peer - } - /// @notice Sender → authorised flag. Gates both outbound `msg.sender` and inbound /// envelopeSender. CreateX/CREATE2 parity means the same address represents the same /// strategy on every chain it lives on. @@ -72,27 +66,6 @@ abstract contract AbstractAdapter is IBridgeAdapter, Governable { /// Internal so the override is the single source of truth externally. uint256 internal _maxTransferAmount; - event Authorised(address indexed sender, ChainConfig cfg); - event Revoked(address indexed sender); - event LaneConfigUpdated(address indexed sender, ChainConfig cfg); - event LanePaused(address indexed sender); - event LaneUnpaused(address indexed sender); - event StrategistAdded(address indexed who); - event StrategistRemoved(address indexed who); - event MaxTransferAmountUpdated(uint256 oldAmount, uint256 newAmount); - event MessageSent( - address indexed sender, - address token, - uint256 amount, - uint256 feeCharged - ); - event MessageDelivered( - address indexed target, - address token, - uint256 amountReceived, - uint256 feePaid - ); - /// @dev Reserved for future expansion of this abstract layer (proxy upgradeable). uint256[50] private __gap; diff --git a/contracts/scripts/deploy/base/003_OETHbV3MasterImpl.s.sol b/contracts/scripts/deploy/base/003_OETHbV3MasterImpl.s.sol index 06b0a98616..c986fab118 100644 --- a/contracts/scripts/deploy/base/003_OETHbV3MasterImpl.s.sol +++ b/contracts/scripts/deploy/base/003_OETHbV3MasterImpl.s.sol @@ -10,7 +10,7 @@ import {GovProposal} from "scripts/deploy/helpers/DeploymentTypes.sol"; // Contracts import {InitializableAbstractStrategy} from "contracts/utils/InitializableAbstractStrategy.sol"; import {MasterWOTokenStrategy} from "contracts/strategies/crosschainV3/MasterWOTokenStrategy.sol"; -import {AbstractAdapter} from "contracts/strategies/crosschainV3/adapters/AbstractAdapter.sol"; +import {IAdapter} from "contracts/interfaces/crosschainV3/IAdapter.sol"; import {CCIPAdapter} from "contracts/strategies/crosschainV3/adapters/CCIPAdapter.sol"; import {SuperbridgeAdapter, IL1StandardBridge} from "contracts/strategies/crosschainV3/adapters/SuperbridgeAdapter.sol"; import {BridgeAdapterProxy} from "contracts/proxies/create2/BridgeAdapterProxy.sol"; @@ -106,7 +106,7 @@ contract $003_OETHbV3MasterImpl is AbstractDeployScript("003_OETHbV3MasterImpl") SuperbridgeAdapter superInbound = SuperbridgeAdapter(payable(superProxy)); // --- 6. Lane configuration --- - AbstractAdapter.ChainConfig memory lane = AbstractAdapter.ChainConfig({ + IAdapter.ChainConfig memory lane = IAdapter.ChainConfig({ paused: false, chainSelector: Mainnet.CCIPChainSelector, destGasLimit: DEST_GAS_LIMIT }); ccipOutbound.authorise(masterProxy, lane); diff --git a/contracts/scripts/deploy/mainnet/007_OETHbV3RemoteImpl.s.sol b/contracts/scripts/deploy/mainnet/007_OETHbV3RemoteImpl.s.sol index 4fb5de6508..07d8019ca6 100644 --- a/contracts/scripts/deploy/mainnet/007_OETHbV3RemoteImpl.s.sol +++ b/contracts/scripts/deploy/mainnet/007_OETHbV3RemoteImpl.s.sol @@ -10,7 +10,7 @@ import {GovProposal} from "scripts/deploy/helpers/DeploymentTypes.sol"; // Contracts import {InitializableAbstractStrategy} from "contracts/utils/InitializableAbstractStrategy.sol"; import {RemoteWOTokenStrategy} from "contracts/strategies/crosschainV3/RemoteWOTokenStrategy.sol"; -import {AbstractAdapter} from "contracts/strategies/crosschainV3/adapters/AbstractAdapter.sol"; +import {IAdapter} from "contracts/interfaces/crosschainV3/IAdapter.sol"; import {CCIPAdapter} from "contracts/strategies/crosschainV3/adapters/CCIPAdapter.sol"; import {SuperbridgeAdapter, IL1StandardBridge} from "contracts/strategies/crosschainV3/adapters/SuperbridgeAdapter.sol"; import {BridgeAdapterProxy} from "contracts/proxies/create2/BridgeAdapterProxy.sol"; @@ -99,9 +99,8 @@ contract $007_OETHbV3RemoteImpl is AbstractDeployScript("007_OETHbV3RemoteImpl") CCIPAdapter ccipInbound = CCIPAdapter(payable(ccipProxy)); // --- 6. Lane configuration --- - AbstractAdapter.ChainConfig memory lane = AbstractAdapter.ChainConfig({ - paused: false, chainSelector: Base.CCIPChainSelector, destGasLimit: DEST_GAS_LIMIT - }); + IAdapter.ChainConfig memory lane = + IAdapter.ChainConfig({paused: false, chainSelector: Base.CCIPChainSelector, destGasLimit: DEST_GAS_LIMIT}); superOutbound.authorise(remoteProxy, lane); ccipInbound.authorise(remoteProxy, lane); diff --git a/contracts/tests/fork/base/strategies/BridgedWOETHMigrationStrategy/shared/Shared.t.sol b/contracts/tests/fork/base/strategies/BridgedWOETHMigrationStrategy/shared/Shared.t.sol index 9300173aef..3a1c63d2da 100644 --- a/contracts/tests/fork/base/strategies/BridgedWOETHMigrationStrategy/shared/Shared.t.sol +++ b/contracts/tests/fork/base/strategies/BridgedWOETHMigrationStrategy/shared/Shared.t.sol @@ -18,6 +18,26 @@ import {IBridgedWOETHMigrationStrategy} from "contracts/interfaces/IBridgedWOETH import {IProxy} from "contracts/interfaces/IProxy.sol"; import {IStrategy} from "contracts/interfaces/IStrategy.sol"; +/// @dev `IBridgedWOETHMigrationStrategy` only declares what the migration contract defines +/// itself; add the inherited `BridgedWOETHStrategy` / `Governable` members the tests read. +interface IBridgedWOETHMigrationStrategyHandle is IBridgedWOETHMigrationStrategy { + function lastOraclePrice() external view returns (uint128); + + function maxPriceDiffBps() external view returns (uint128); + + function weth() external view returns (address); + + function bridgedWOETH() external view returns (address); + + function oethb() external view returns (address); + + function oracle() external view returns (address); + + function vaultAddress() external view returns (address); + + function governor() external view returns (address); +} + struct BaseStrategyConfig { address platformAddress; address vaultAddress; @@ -44,7 +64,7 @@ abstract contract Fork_BridgedWOETHMigrationStrategy_Shared_Test is BaseFork { /// --- CONTRACTS ////////////////////////////////////////////////////// - IBridgedWOETHMigrationStrategy internal migration; + IBridgedWOETHMigrationStrategyHandle internal migration; IStrategy internal master; IERC20 internal woeth; address internal ccipRouter; @@ -108,7 +128,7 @@ abstract contract Fork_BridgedWOETHMigrationStrategy_Shared_Test is BaseFork { vm.startPrank(BaseAddresses.timelock); IProxy(BaseAddresses.BridgedWOETHStrategyProxy).upgradeTo(migrationImpl); - migration = IBridgedWOETHMigrationStrategy(BaseAddresses.BridgedWOETHStrategyProxy); + migration = IBridgedWOETHMigrationStrategyHandle(BaseAddresses.BridgedWOETHStrategyProxy); migration.setMaxPerBridge(MAX_PER_BRIDGE); vm.stopPrank(); diff --git a/contracts/tests/fork/mainnet/strategies/RemoteWOTokenStrategy/shared/Shared.t.sol b/contracts/tests/fork/mainnet/strategies/RemoteWOTokenStrategy/shared/Shared.t.sol index 649ab992d9..02813445bd 100644 --- a/contracts/tests/fork/mainnet/strategies/RemoteWOTokenStrategy/shared/Shared.t.sol +++ b/contracts/tests/fork/mainnet/strategies/RemoteWOTokenStrategy/shared/Shared.t.sol @@ -18,6 +18,14 @@ import {IAdapter} from "contracts/interfaces/crosschainV3/IAdapter.sol"; import {IRemoteWOTokenStrategy} from "contracts/interfaces/crosschainV3/IRemoteWOTokenStrategy.sol"; import {IProxy} from "contracts/interfaces/IProxy.sol"; +/// @dev `IRemoteWOTokenStrategy` only declares what Remote defines itself; add the inherited +/// `AbstractCrossChainV3Strategy` setters the fixture calls. +interface IRemoteWOTokenStrategyHandle is IRemoteWOTokenStrategy { + function setInboundAdapter(address adapter) external; + + function setOutboundAdapter(address adapter) external; +} + struct BaseStrategyConfig { address platformAddress; address vaultAddress; @@ -49,7 +57,7 @@ abstract contract Fork_RemoteWOTokenStrategy_Shared_Test is BaseFork { /// --- CONTRACTS ////////////////////////////////////////////////////// - IRemoteWOTokenStrategy internal remote; + IRemoteWOTokenStrategyHandle internal remote; IAdapter internal ccipAdapter; IAdapter internal superbridgeAdapter; IERC20 internal woeth; @@ -94,7 +102,7 @@ abstract contract Fork_RemoteWOTokenStrategy_Shared_Test is BaseFork { vm.prank(governor); strategyProxy.initialize(strategyImpl, governor, abi.encodeWithSignature("initialize(address)", operator)); - remote = IRemoteWOTokenStrategy(address(strategyProxy)); + remote = IRemoteWOTokenStrategyHandle(address(strategyProxy)); // Inbound on Ethereum is CCIP (Base -> Ethereum). Outbound is Superbridge // (Ethereum -> Base): canonical ETH leg + CCIP message.