Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Raunak/upgradeable uch #87

Merged
merged 2 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions contracts/core/UniversalChannelHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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";
RnkSngh marked this conversation as resolved.
Show resolved Hide resolved
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;
Expand All @@ -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.
Expand Down Expand Up @@ -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)
Expand Down
33 changes: 33 additions & 0 deletions contracts/interfaces/IUniversalChannelHandler.sol
Original file line number Diff line number Diff line change
@@ -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);
}
45 changes: 45 additions & 0 deletions contracts/interfaces/IbcReceiverUpgradeable.sol
Original file line number Diff line number Diff line change
@@ -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;
}
}
16 changes: 13 additions & 3 deletions script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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_) {
Expand Down
20 changes: 18 additions & 2 deletions test/TestUtils.t.sol
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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))));
}
Expand Down
19 changes: 10 additions & 9 deletions test/VirtualChain.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -27,7 +28,7 @@ struct ChannelSetting {

struct VirtualChainData {
IDispatcher dispatcherProxy;
UniversalChannelHandler ucHandler;
IUniversalChannelHandler ucHandlerProxy;
Mars mars;
Earth earth;
GeneralMiddleware mw1;
Expand All @@ -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;

Expand All @@ -60,26 +61,26 @@ 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])));
}
connectionHops = new string[](2);
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
Expand Down Expand Up @@ -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);
}

Expand Down
Loading
Loading