diff --git a/contracts/core/UniversalChannelHandler.sol b/contracts/core/UniversalChannelHandler.sol index ac236963..d1fcbd23 100644 --- a/contracts/core/UniversalChannelHandler.sol +++ b/contracts/core/UniversalChannelHandler.sol @@ -11,10 +11,13 @@ import { IbcMwPacketReceiver, IbcMwEventsEmitter } from "../interfaces/IbcMiddleware.sol"; -import {IbcReceiver, IbcReceiverBase} from "../interfaces/IbcReceiver.sol"; +import {IbcReceiver} from "../interfaces/IbcReceiver.sol"; +import {IbcReceiverBaseUpgradeable} from "../interfaces/IbcReceiverUpgradeable.sol"; import {ChannelOrder, ChannelEnd, IbcPacket, AckPacket, UniversalPacket, IbcUtils} from "../libs/Ibc.sol"; -contract UniversalChannelHandler is IbcReceiverBase, IbcUniversalChannelMW { +contract UniversalChannelHandler is IbcReceiverBaseUpgradeable, IbcUniversalChannelMW { + uint256[49] private __gap; + bytes32[] public connectedChannels; string public constant VERSION = "1.0"; uint256 public constant MW_ID = 1; @@ -24,7 +27,13 @@ contract UniversalChannelHandler is IbcReceiverBase, IbcUniversalChannelMW { event UCHPacketSent(address source, bytes32 destination); - constructor(IbcDispatcher _dispatcher) IbcReceiverBase(_dispatcher) {} + constructor() { + _disableInitializers(); + } + + function initialize(IbcDispatcher _dispatcher) public initializer { + __IbcReceiverBase_init(_dispatcher); + } /** * @dev Close a universal channel. * Cannot send or receive packets after the channel is closed. @@ -182,6 +191,10 @@ contract UniversalChannelHandler is IbcReceiverBase, IbcUniversalChannelMW { function onChanOpenConfirm(bytes32 channelId) external onlyIbcDispatcher {} + function setDispatcher(IbcDispatcher _dispatcher) external onlyOwner { + dispatcher = _dispatcher; + } + function _connectChannel(bytes32 channelId, string calldata version) internal returns (string memory checkedVersion) diff --git a/contracts/interfaces/IUniversalChannelHandler.sol b/contracts/interfaces/IUniversalChannelHandler.sol new file mode 100644 index 00000000..7a1d4c91 --- /dev/null +++ b/contracts/interfaces/IUniversalChannelHandler.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IbcDispatcher, IbcEventsEmitter} from "./IbcDispatcher.sol"; + +import {L1Header, OpL2StateProof, Ics23Proof} from "./ProofVerifier.sol"; +import {IbcUniversalChannelMW} from "./IbcMiddleware.sol"; +import { + Channel, + ChannelEnd, + ChannelOrder, + IbcPacket, + ChannelState, + AckPacket, + IBCErrors, + IbcUtils, + Ibc +} from "../libs/Ibc.sol"; + +interface IUniversalChannelHandler is IbcUniversalChannelMW { + function registerMwStack(uint256 mwBitmap, address[] calldata mwAddrs) external; + function openChannel( + string calldata version, + ChannelOrder ordering, + bool feeEnabled, + string[] calldata connectionHops, + string calldata counterpartyPortIdentifier + ) external; + function closeChannel(bytes32 channelId) external; + function setDispatcher(IbcDispatcher dispatcher) external; + function dispatcher() external returns (IbcDispatcher dispatcher); + function connectedChannels(uint256) external view returns (bytes32 channel); +} diff --git a/contracts/interfaces/IbcReceiverUpgradeable.sol b/contracts/interfaces/IbcReceiverUpgradeable.sol new file mode 100644 index 00000000..f748f962 --- /dev/null +++ b/contracts/interfaces/IbcReceiverUpgradeable.sol @@ -0,0 +1,45 @@ +//SPDX-License-Identifier: UNLICENSED + +pragma solidity ^0.8.9; + +import {OwnableUpgradeable} from "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; +import {IbcDispatcher} from "./IbcDispatcher.sol"; +import {ChannelOrder, ChannelEnd, IbcPacket, AckPacket} from "../libs/Ibc.sol"; + +contract IbcReceiverBaseUpgradeable is OwnableUpgradeable { + IbcDispatcher public dispatcher; + + error notIbcDispatcher(); + error UnsupportedVersion(); + error ChannelNotFound(); + + /** + * @dev Modifier to restrict access to only the IBC dispatcher. + * Only the address with the IBC_ROLE can execute the function. + * Should add this modifier to all IBC-related callback functions. + */ + modifier onlyIbcDispatcher() { + if (msg.sender != address(dispatcher)) { + revert notIbcDispatcher(); + } + _; + } + + constructor() { + _disableInitializers(); + } + + /// This function is called for plain Ether transfers, i.e. for every call with empty calldata. + // An empty function body is sufficient to receive packet fee refunds. + receive() external payable {} + + /** + * @dev initializer function that takes an IbcDispatcher address and grants the IBC_ROLE to the Polymer IBC + * Dispatcher. + * @param _dispatcher The address of the IbcDispatcher contract. + */ + function __IbcReceiverBase_init(IbcDispatcher _dispatcher) internal onlyInitializing { + __Ownable_init(); + dispatcher = _dispatcher; + } +} diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index be637c25..3453a405 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -7,6 +7,7 @@ import "../contracts/utils/DummyLightClient.sol"; import "../contracts/core/Dispatcher.sol"; import {Mars} from "../contracts/examples/Mars.sol"; import {IDispatcher} from "../contracts/core/Dispatcher.sol"; +import {IUniversalChannelHandler} from "../contracts/interfaces/IUniversalChannelHandler.sol"; import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import "../contracts/core/OpProofVerifier.sol"; import "../contracts/core/OpLightClient.sol"; @@ -106,9 +107,18 @@ contract Deploy is Script { } function deployUniversalChannelHandler(address dispatcher) public broadcast returns (address addr_) { - UniversalChannelHandler handler = new UniversalChannelHandler{salt: _implSalt()}(IbcDispatcher(dispatcher)); - console.log("UniversalChannelHandler deployed at %s", address(handler)); - return address(handler); + UniversalChannelHandler uchImplementation = new UniversalChannelHandler(); + IUniversalChannelHandler proxy = IUniversalChannelHandler( + address( + new ERC1967Proxy( + address(uchImplementation), + abi.encodeWithSelector(UniversalChannelHandler.initialize.selector, dispatcher) + ) + ) + ); + console.log("UniversalChannelHandler implementation deployed at %s", address(uchImplementation)); + console.log("UniversalChannelHandler proxy deployed at %s", address(proxy)); + return address(proxy); } function deployEarth(address middleware) public broadcast returns (address addr_) { diff --git a/test/TestUtils.t.sol b/test/TestUtils.t.sol index 9c6055ed..99123d46 100644 --- a/test/TestUtils.t.sol +++ b/test/TestUtils.t.sol @@ -1,11 +1,12 @@ import {IDispatcher} from "../contracts/interfaces/IDispatcher.sol"; +import {IUniversalChannelHandler} from "../contracts/interfaces/IUniversalChannelHandler.sol"; import {LightClient} from "../contracts/interfaces/LightClient.sol"; import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import {Dispatcher} from "../contracts/core/Dispatcher.sol"; -// import {StdCheats} from "../forge-std/StdCheats.sol"; +import {UniversalChannelHandler} from "../contracts/core/UniversalChannelHandler.sol"; + import {Test} from "forge-std/Test.sol"; import {Vm} from "forge-std/Vm.sol"; -// import {StdCheats} from "forge-std/StdCheats.sol"; pragma solidity ^0.8.0; @@ -29,6 +30,21 @@ abstract contract TestUtilsTest { ); } + function deployUCHProxyAndImpl(address dispatcherProxy) + public + returns (IUniversalChannelHandler proxy, UniversalChannelHandler uchImplementation) + { + uchImplementation = new UniversalChannelHandler(); + proxy = IUniversalChannelHandler( + address( + new ERC1967Proxy( + address(uchImplementation), + abi.encodeWithSelector(UniversalChannelHandler.initialize.selector, dispatcherProxy) + ) + ) + ); + } + function getProxyImplementation(address proxy, Vm vm) public view returns (address dispatcherImplementation) { dispatcherImplementation = address(uint160(uint256(vm.load(address(proxy), _IMPLEMENTATION_SLOT)))); } diff --git a/test/VirtualChain.sol b/test/VirtualChain.sol index da76f70b..4630be42 100644 --- a/test/VirtualChain.sol +++ b/test/VirtualChain.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.13; import "forge-std/Test.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import {IbcDispatcher, IbcEventsEmitter} from "../contracts/interfaces/IbcDispatcher.sol"; +import {IUniversalChannelHandler} from "../contracts/interfaces/IUniversalChannelHandler.sol"; import {IDispatcher} from "../contracts/interfaces/IDispatcher.sol"; import "../contracts/libs/Ibc.sol"; import "../contracts/core/Dispatcher.sol"; @@ -27,7 +28,7 @@ struct ChannelSetting { struct VirtualChainData { IDispatcher dispatcherProxy; - UniversalChannelHandler ucHandler; + IUniversalChannelHandler ucHandlerProxy; Mars mars; Earth earth; GeneralMiddleware mw1; @@ -39,7 +40,7 @@ struct VirtualChainData { contract VirtualChain is Test, IbcEventsEmitter, TestUtilsTest { IDispatcher public dispatcherProxy; Dispatcher public dispatcherImplementation; - UniversalChannelHandler public ucHandler; + IUniversalChannelHandler public ucHandlerProxy; GeneralMiddleware public mw1; GeneralMiddleware public mw2; @@ -60,12 +61,12 @@ contract VirtualChain is Test, IbcEventsEmitter, TestUtilsTest { _seed = seed; (dispatcherProxy, dispatcherImplementation) = deployDispatcherProxyAndImpl(portPrefix, new DummyLightClient()); - ucHandler = new UniversalChannelHandler(dispatcherProxy); + (ucHandlerProxy,) = deployUCHProxyAndImpl(address(dispatcherProxy)); mars = new Mars(dispatcherProxy); - earth = new Earth(address(ucHandler)); + earth = new Earth(address(ucHandlerProxy)); // initialize portIds for counterparty chains - address[3] memory portContracts = [address(ucHandler), address(mars), address(earth)]; + address[3] memory portContracts = [address(ucHandlerProxy), address(mars), address(earth)]; for (uint256 i = 0; i < portContracts.length; i++) { portIds[portContracts[i]] = string(abi.encodePacked(portPrefix, toHexStr(portContracts[i]))); } @@ -73,13 +74,13 @@ contract VirtualChain is Test, IbcEventsEmitter, TestUtilsTest { connectionHops[0] = newConnectionId(); connectionHops[1] = newConnectionId(); - mw1 = new GeneralMiddleware(1 << 1, address(ucHandler)); - mw2 = new GeneralMiddleware(1 << 2, address(ucHandler)); + mw1 = new GeneralMiddleware(1 << 1, address(ucHandlerProxy)); + mw2 = new GeneralMiddleware(1 << 2, address(ucHandlerProxy)); } // return virtualChainData function getVirtualChainData() external view returns (VirtualChainData memory) { - return VirtualChainData(dispatcherProxy, ucHandler, mars, earth, mw1, mw2, connectionHops); + return VirtualChainData(dispatcherProxy, ucHandlerProxy, mars, earth, mw1, mw2, connectionHops); } // expectedChannel returns a Channel struct with expected values @@ -167,7 +168,7 @@ contract VirtualChain is Test, IbcEventsEmitter, TestUtilsTest { remoteChain.portIds(address(remoteEnd)) ); } - vm.prank(address(ucHandler)); + vm.prank(address(ucHandlerProxy)); dispatcherProxy.channelOpenInit(setting.version, setting.ordering, setting.feeEnabled, connectionHops, cpPortId); } diff --git a/test/universal.channel.t.sol b/test/universal.channel.t.sol index abd2b736..37a0e571 100644 --- a/test/universal.channel.t.sol +++ b/test/universal.channel.t.sol @@ -29,7 +29,7 @@ contract UniversalChannelTest is Base { feesEnabled[j], validProof ); - eth1.finishHandshake(eth1.ucHandler(), eth2, eth2.ucHandler(), setting); + eth1.finishHandshake(eth1.ucHandlerProxy(), eth2, eth2.ucHandlerProxy(), setting); assert_channel(eth1, eth2, setting); } @@ -37,17 +37,17 @@ contract UniversalChannelTest is Base { } function assert_channel(VirtualChain vc1, VirtualChain vc2, ChannelSetting memory setting) internal { - bytes32 channelId1 = vc1.channelIds(address(vc1.ucHandler()), address(vc2.ucHandler())); - bytes32 channelId2 = vc2.channelIds(address(vc2.ucHandler()), address(vc1.ucHandler())); - assertEq(vc1.ucHandler().connectedChannels(0), channelId1, "channels not equal 1"); - assertEq(vc2.ucHandler().connectedChannels(0), channelId2, "channels not equal 2"); + bytes32 channelId1 = vc1.channelIds(address(vc1.ucHandlerProxy()), address(vc2.ucHandlerProxy())); + bytes32 channelId2 = vc2.channelIds(address(vc2.ucHandlerProxy()), address(vc1.ucHandlerProxy())); + assertEq(vc1.ucHandlerProxy().connectedChannels(0), channelId1, "channels not equal 1"); + assertEq(vc2.ucHandlerProxy().connectedChannels(0), channelId2, "channels not equal 2"); - Channel memory channel1 = vc1.dispatcherProxy().getChannel(address(vc1.ucHandler()), channelId1); - Channel memory channel2 = vc2.dispatcherProxy().getChannel(address(vc2.ucHandler()), channelId2); + Channel memory channel1 = vc1.dispatcherProxy().getChannel(address(vc1.ucHandlerProxy()), channelId1); + Channel memory channel2 = vc2.dispatcherProxy().getChannel(address(vc2.ucHandlerProxy()), channelId2); Channel memory channel2Expected = - vc1.expectedChannel(address(vc1.ucHandler()), channelId1, vc2.getConnectionHops(), setting); + vc1.expectedChannel(address(vc1.ucHandlerProxy()), channelId1, vc2.getConnectionHops(), setting); Channel memory channel1Expected = - vc2.expectedChannel(address(vc2.ucHandler()), channelId2, vc1.getConnectionHops(), setting); + vc2.expectedChannel(address(vc2.ucHandlerProxy()), channelId2, vc1.getConnectionHops(), setting); assertEq(abi.encode(channel1), abi.encode(channel1Expected)); assertEq(abi.encode(channel2), abi.encode(channel2Expected)); } @@ -65,8 +65,8 @@ contract UniversalChannelTest is Base { validProof ); - IbcChannelReceiver ucHandler1 = eth1.ucHandler(); - IbcChannelReceiver ucHandler2 = eth2.ucHandler(); + IbcChannelReceiver ucHandler1 = eth1.ucHandlerProxy(); + IbcChannelReceiver ucHandler2 = eth2.ucHandlerProxy(); eth1.assignChannelIds(ucHandler1, ucHandler2, eth2); address unauthorized = deriveAddress("unauthorized"); @@ -127,14 +127,14 @@ contract UniversalChannelPacketTest is Base, IbcMwEventsEmitter { ); eth1 = new VirtualChain(100, "polyibc.eth1."); eth2 = new VirtualChain(200, "polyibc.eth2."); - eth1.finishHandshake(eth1.ucHandler(), eth2, eth2.ucHandler(), setting); + eth1.finishHandshake(eth1.ucHandlerProxy(), eth2, eth2.ucHandlerProxy(), setting); v1 = eth1.getVirtualChainData(); v2 = eth2.getVirtualChainData(); } // register middleware stack: dApp -> mw1 -> UniversalChannel MW function register_mw1() internal returns (uint256) { - uint256 mwBitmap = v1.ucHandler.MW_ID() | v1.mw1.MW_ID(); + uint256 mwBitmap = v1.ucHandlerProxy.MW_ID() | v1.mw1.MW_ID(); address[] memory mwAddrs = new address[](1); // change Earth's default middleware to mw1, which sits on top of UniversalChannel MW @@ -142,14 +142,14 @@ contract UniversalChannelPacketTest is Base, IbcMwEventsEmitter { v1.earth.setDefaultMw(address(v1.mw1)); // register mw1 as the only middleware in the stack mwAddrs[0] = address(v1.mw1); - v1.ucHandler.registerMwStack(mwBitmap, mwAddrs); + v1.ucHandlerProxy.registerMwStack(mwBitmap, mwAddrs); vm.stopPrank(); vm.startPrank(address(eth2)); v2.earth.setDefaultMw(address(v2.mw1)); // register mw1 as the only middleware in the stack mwAddrs[0] = address(v2.mw1); - v2.ucHandler.registerMwStack(mwBitmap, mwAddrs); + v2.ucHandlerProxy.registerMwStack(mwBitmap, mwAddrs); vm.stopPrank(); return mwBitmap; @@ -158,7 +158,7 @@ contract UniversalChannelPacketTest is Base, IbcMwEventsEmitter { // register middleware stack: dApp -> mw1 -> mw2 -> UniversalChannel MW function register_mw1_mw2() internal returns (uint256) { address[] memory mwAddrs = new address[](2); - uint256 mwBitmap = v1.ucHandler.MW_ID() | v1.mw1.MW_ID() | v2.mw2.MW_ID(); + uint256 mwBitmap = v1.ucHandlerProxy.MW_ID() | v1.mw1.MW_ID() | v2.mw2.MW_ID(); // change Earth's default middleware to mw1, which calls mw2, then UniversalChannel MW vm.startPrank(address(eth1)); @@ -168,7 +168,7 @@ contract UniversalChannelPacketTest is Base, IbcMwEventsEmitter { mwAddrs[0] = address(v1.mw2); mwAddrs[1] = address(v1.mw1); - v1.ucHandler.registerMwStack(mwBitmap, mwAddrs); + v1.ucHandlerProxy.registerMwStack(mwBitmap, mwAddrs); vm.stopPrank(); vm.startPrank(address(eth2)); @@ -177,7 +177,7 @@ contract UniversalChannelPacketTest is Base, IbcMwEventsEmitter { // register middleware stack mwAddrs[0] = address(v2.mw2); mwAddrs[1] = address(v2.mw1); - v2.ucHandler.registerMwStack(mwBitmap, mwAddrs); + v2.ucHandlerProxy.registerMwStack(mwBitmap, mwAddrs); vm.stopPrank(); return mwBitmap; @@ -191,7 +191,7 @@ contract UniversalChannelPacketTest is Base, IbcMwEventsEmitter { // packet flow: Earth -> UC -> Dispatcher -> (Relayer) -> Dispatcher -> UC -> Earth function test_packetFlow_via_universal_channel_ok() public { - uint256 mwBitmap = v1.ucHandler.MW_ID(); + uint256 mwBitmap = v1.ucHandlerProxy.MW_ID(); verifyPacketFlow(5, mwBitmap); } @@ -208,7 +208,7 @@ contract UniversalChannelPacketTest is Base, IbcMwEventsEmitter { } function test_timeout_via_universal_channel_ok() public { - uint256 mwBitmap = v1.ucHandler.MW_ID(); + uint256 mwBitmap = v1.ucHandlerProxy.MW_ID(); verifyTimeoutFlow(5, mwBitmap); } @@ -222,6 +222,29 @@ contract UniversalChannelPacketTest is Base, IbcMwEventsEmitter { verifyTimeoutFlow(5, mwBitmap); } + function test_uch_new_dispatcher_set_ok() public { + IUniversalChannelHandler uch = eth1.ucHandlerProxy(); + vm.startPrank(address(eth1)); // Prank eth1 since that address is the owner + (IDispatcher newDispatcher,) = deployDispatcherProxyAndImpl("polyibc.new.", dummyConsStateManager); + assertFalse( + address(uch.dispatcher()) == address(newDispatcher), "new dispatcher in uch test not setup correctly" + ); + uch.setDispatcher(newDispatcher); + assertEq(address(uch.dispatcher()), address(newDispatcher), "new dispatcher not set correctly in uch"); + vm.stopPrank(); + } + + function test_nonOwner_cannot_set_uch_dispatcher() public { + IUniversalChannelHandler uch = eth1.ucHandlerProxy(); + address notOwner = vm.addr(1); + vm.startPrank(notOwner); + (IDispatcher newDispatcher,) = deployDispatcherProxyAndImpl("polyibc.new.", dummyConsStateManager); + + vm.expectRevert("Ownable: caller is not the owner"); + uch.setDispatcher(newDispatcher); + vm.stopPrank(); + } + /** * Test packet flow from chain A to chain B via UniversalChannel MW and optionally other MW that sits on top of * UniversalChannel MW. @@ -230,8 +253,8 @@ contract UniversalChannelPacketTest is Base, IbcMwEventsEmitter { */ function verifyTimeoutFlow(uint64 numOfPackets, uint256 mwBitmap) internal { // universal channelIDs - bytes32 channelId1 = eth1.channelIds(address(eth1.ucHandler()), address(eth2.ucHandler())); - bytes32 channelId2 = eth2.channelIds(address(eth2.ucHandler()), address(eth1.ucHandler())); + bytes32 channelId1 = eth1.channelIds(address(eth1.ucHandlerProxy()), address(eth2.ucHandlerProxy())); + bytes32 channelId2 = eth2.channelIds(address(eth2.ucHandlerProxy()), address(eth1.ucHandlerProxy())); GeneralMiddleware[2] memory senderMws = [v1.mw1, v1.mw2]; for (uint64 packetSeq = 1; packetSeq <= numOfPackets; packetSeq++) { @@ -263,15 +286,15 @@ contract UniversalChannelPacketTest is Base, IbcMwEventsEmitter { } // Verify event emitted by Dispatcher vm.expectEmit(true, true, true, true); - emit SendPacket(address(v1.ucHandler), channelId1, packetData, packetSeq, timeout); + emit SendPacket(address(v1.ucHandlerProxy), channelId1, packetData, packetSeq, timeout); v1.earth.greet(address(v2.earth), channelId1, appData, timeout); // simulate relayer calling dispatcherProxy.recvPacket on chain B // recvPacket is an IBC packet recvPacket = IbcPacket( - IbcEndpoint(eth1.portIds(address(v1.ucHandler)), channelId1), - IbcEndpoint(eth2.portIds(address(v2.ucHandler)), channelId2), + IbcEndpoint(eth1.portIds(address(v1.ucHandlerProxy)), channelId1), + IbcEndpoint(eth2.portIds(address(v2.ucHandlerProxy)), channelId2), packetSeq, packetData, Height(0, 0), @@ -300,7 +323,7 @@ contract UniversalChannelPacketTest is Base, IbcMwEventsEmitter { } // verify event emitted by Dispatcher vm.expectEmit(true, true, true, true); - emit Timeout(address(v1.ucHandler), channelId1, packetSeq); + emit Timeout(address(v1.ucHandlerProxy), channelId1, packetSeq); // receive ack on chain A, triggering expected events v1.dispatcherProxy.timeout(recvPacket, validProof); @@ -319,8 +342,8 @@ contract UniversalChannelPacketTest is Base, IbcMwEventsEmitter { */ function verifyPacketFlow(uint64 numOfPackets, uint256 mwBitmap) internal { // universal channelIDs - bytes32 channelId1 = eth1.channelIds(address(eth1.ucHandler()), address(eth2.ucHandler())); - bytes32 channelId2 = eth2.channelIds(address(eth2.ucHandler()), address(eth1.ucHandler())); + bytes32 channelId1 = eth1.channelIds(address(eth1.ucHandlerProxy()), address(eth2.ucHandlerProxy())); + bytes32 channelId2 = eth2.channelIds(address(eth2.ucHandlerProxy()), address(eth1.ucHandlerProxy())); GeneralMiddleware[2] memory senderMws = [v1.mw1, v1.mw2]; GeneralMiddleware[2] memory recvMws = [v2.mw2, v1.mw1]; @@ -353,14 +376,14 @@ contract UniversalChannelPacketTest is Base, IbcMwEventsEmitter { // Verify event emitted by Dispatcher vm.expectEmit(true, true, true, true); - emit SendPacket(address(v1.ucHandler), channelId1, packetData, packetSeq, timeout); + emit SendPacket(address(v1.ucHandlerProxy), channelId1, packetData, packetSeq, timeout); v1.earth.greet(address(v2.earth), channelId1, appData, timeout); // simulate relayer calling dispatcherProxy.recvPacket on chain B // recvPacket is an IBC packet recvPacket = IbcPacket( - IbcEndpoint(eth1.portIds(address(v1.ucHandler)), channelId1), - IbcEndpoint(eth2.portIds(address(v2.ucHandler)), channelId2), + IbcEndpoint(eth1.portIds(address(v1.ucHandlerProxy)), channelId1), + IbcEndpoint(eth2.portIds(address(v2.ucHandlerProxy)), channelId2), packetSeq, packetData, Height(0, 0), @@ -370,7 +393,7 @@ contract UniversalChannelPacketTest is Base, IbcMwEventsEmitter { ackPacket = v2.earth.generateAckPacket(channelId2, address(v1.earth), appData); // verify event emitted by Dispatcher vm.expectEmit(true, true, true, true); - emit RecvPacket(address(v2.ucHandler), channelId2, packetSeq); + emit RecvPacket(address(v2.ucHandlerProxy), channelId2, packetSeq); // iterate over receiving middleware contracts to verify each MW has witnessed the packet for (uint256 i = 0; i < recvMws.length; i++) { if (recvMws[i].MW_ID() == (recvMws[i].MW_ID() & mwBitmap)) { @@ -387,7 +410,7 @@ contract UniversalChannelPacketTest is Base, IbcMwEventsEmitter { } // verify event emitted by Dispatcher vm.expectEmit(true, true, true, true); - emit WriteAckPacket(address(v2.ucHandler), channelId2, packetSeq, ackPacket); + emit WriteAckPacket(address(v2.ucHandlerProxy), channelId2, packetSeq, ackPacket); v2.dispatcherProxy.recvPacket(recvPacket, validProof); // verify packet received by Earth on chain B @@ -418,7 +441,7 @@ contract UniversalChannelPacketTest is Base, IbcMwEventsEmitter { } // verify event emitted by Dispatcher vm.expectEmit(true, true, true, true); - emit Acknowledgement(address(v1.ucHandler), channelId1, packetSeq); + emit Acknowledgement(address(v1.ucHandlerProxy), channelId1, packetSeq); // receive ack on chain A, triggering expected events v1.dispatcherProxy.acknowledgement(recvPacket, ackToBytes(ackPacket), validProof);