Skip to content
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
Original file line number Diff line number Diff line change
@@ -1,91 +1,11 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.20;

import {Channel, UpgradeFields, Timeout} from "../../../../contracts/proto/Channel.sol";
import {IIBCHandler} from "../../../../contracts/core/25-handler/IIBCHandler.sol";
import {IIBCModuleUpgrade} from "../../../../contracts/core/26-router/IIBCModuleUpgrade.sol";
import {AppBase} from "../../../../contracts/apps/commons/IBCAppBase.sol";

interface IIBCChannelUpgradableModuleErrors {
// ------------------- Errors ------------------- //

error IBCChannelUpgradableModuleUnauthorizedUpgrader();
error IBCChannelUpgradableModuleInvalidTimeout();
error IBCChannelUpgradableModuleInvalidConnectionHops();
error IBCChannelUpgradableModuleUpgradeAlreadyExists();
error IBCChannelUpgradableModuleUpgradeNotFound();
error IBCChannelUpgradableModuleInvalidUpgrade();

error IBCChannelUpgradableModuleCannotRemoveInProgressUpgrade();
/// @param state The current state of the channel
error IBCChannelUpgradableModuleChannelNotFlushingState(Channel.State state);
/// @param actual The actual upgrade sequence
error IBCChannelUpgradableModuleSequenceMismatch(uint64 actual);

error IBCChannelUpgradableModuleChannelNotFound();
error IBCChannelUpgradableModuleCannotOverwriteUpgrade();
}

interface IIBCChannelUpgradableModule {
// ------------------- Data Structures ------------------- //

/**
* @dev Proposed upgrade fields
* @param fields Upgrade fields
* @param timeout Absolute timeout for the upgrade
*/
struct UpgradeProposal {
UpgradeFields.Data fields;
Timeout.Data timeout;
}

/**
* @dev Allowed transition for the channel upgrade
* @param flushComplete Whether the upgrade is allowed to transition to the flush complete state
*/
struct AllowedTransition {
bool flushComplete;
}

// ------------------- Functions ------------------- //

/**
* @dev Returns the proposed upgrade for the given port, channel, and sequence
*/
function getUpgradeProposal(string calldata portId, string calldata channelId)
external
view
returns (UpgradeProposal memory);

/**
* @dev Propose an upgrade for the given port, channel, and sequence
* @notice This function is only callable by an authorized upgrader
* The upgrader must call this function before calling `channelUpgradeInit` or `channelUpgradeTry` of the IBC handler
*/
function proposeUpgrade(
string calldata portId,
string calldata channelId,
UpgradeFields.Data calldata upgradeFields,
Timeout.Data calldata timeout
) external;

/**
* @dev Removes the proposed upgrade for the given port and channel
* @notice This function is only callable by an authorized upgrader
* @param portId Port identifier
* @param channelId Channel identifier
*/
function removeUpgradeProposal(string calldata portId, string calldata channelId) external;

/**
* @dev Allow the upgrade to transition to the flush complete state
* @notice This function is only callable by an authorized upgrader
* WARNING: Before calling this function, the upgrader must ensure that all inflight packets have been received on the receiving chain,
* and all acknowledgements written have been acknowledged on the sending chain
*/
function allowTransitionToFlushComplete(string calldata portId, string calldata channelId, uint64 upgradeSequence)
external;
}
import {Channel, UpgradeFields, Timeout} from "../../proto/Channel.sol";
import {IIBCHandler} from "../../core/25-handler/IIBCHandler.sol";
import {IIBCModuleUpgrade} from "../../core/26-router/IIBCModuleUpgrade.sol";
import {AppBase} from "./IBCAppBase.sol";
import {IIBCChannelUpgradableModule, IIBCChannelUpgradableModuleErrors} from "./IIBCChannelUpgradableModule.sol";

abstract contract IBCChannelUpgradableModuleBase is
AppBase,
Expand Down Expand Up @@ -312,10 +232,8 @@ abstract contract IBCChannelUpgradableModuleBase is
* @dev See {IERC165-supportsInterface}
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return
super.supportsInterface(interfaceId) ||
interfaceId == type(IIBCModuleUpgrade).interfaceId ||
interfaceId == type(IIBCChannelUpgradableModule).interfaceId;
return super.supportsInterface(interfaceId) || interfaceId == type(IIBCModuleUpgrade).interfaceId
|| interfaceId == type(IIBCChannelUpgradableModule).interfaceId;
}

// ------------------- Internal Functions ------------------- //
Expand Down
85 changes: 85 additions & 0 deletions contracts/apps/commons/IIBCChannelUpgradableModule.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.20;

import {Channel, UpgradeFields, Timeout} from "../../proto/Channel.sol";

interface IIBCChannelUpgradableModuleErrors {
// ------------------- Errors ------------------- //

error IBCChannelUpgradableModuleUnauthorizedUpgrader();
error IBCChannelUpgradableModuleInvalidTimeout();
error IBCChannelUpgradableModuleInvalidConnectionHops();
error IBCChannelUpgradableModuleUpgradeAlreadyExists();
error IBCChannelUpgradableModuleUpgradeNotFound();
error IBCChannelUpgradableModuleInvalidUpgrade();

error IBCChannelUpgradableModuleCannotRemoveInProgressUpgrade();
/// @param state The current state of the channel
error IBCChannelUpgradableModuleChannelNotFlushingState(Channel.State state);
/// @param actual The actual upgrade sequence
error IBCChannelUpgradableModuleSequenceMismatch(uint64 actual);

error IBCChannelUpgradableModuleChannelNotFound();
error IBCChannelUpgradableModuleCannotOverwriteUpgrade();
}

interface IIBCChannelUpgradableModule {
// ------------------- Data Structures ------------------- //

/**
* @dev Proposed upgrade fields
* @param fields Upgrade fields
* @param timeout Absolute timeout for the upgrade
*/
struct UpgradeProposal {
UpgradeFields.Data fields;
Timeout.Data timeout;
}

/**
* @dev Allowed transition for the channel upgrade
* @param flushComplete Whether the upgrade is allowed to transition to the flush complete state
*/
struct AllowedTransition {
bool flushComplete;
}

// ------------------- Functions ------------------- //

/**
* @dev Returns the proposed upgrade for the given port, channel, and sequence
*/
function getUpgradeProposal(string calldata portId, string calldata channelId)
external
view
returns (UpgradeProposal memory);

/**
* @dev Propose an upgrade for the given port, channel, and sequence
* @notice This function is only callable by an authorized upgrader
* The upgrader must call this function before calling `channelUpgradeInit` or `channelUpgradeTry` of the IBC handler
*/
function proposeUpgrade(
string calldata portId,
string calldata channelId,
UpgradeFields.Data calldata upgradeFields,
Timeout.Data calldata timeout
) external;

/**
* @dev Removes the proposed upgrade for the given port and channel
* @notice This function is only callable by an authorized upgrader
* @param portId Port identifier
* @param channelId Channel identifier
*/
function removeUpgradeProposal(string calldata portId, string calldata channelId) external;

/**
* @dev Allow the upgrade to transition to the flush complete state
* @notice This function is only callable by an authorized upgrader
* WARNING: Before calling this function, the upgrader must ensure that all inflight packets have been received on the receiving chain,
* and all acknowledgements written have been acknowledged on the sending chain
*/
function allowTransitionToFlushComplete(string calldata portId, string calldata channelId, uint64 upgradeSequence)
external;
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.20;

import {Upgrade, UpgradeFields, Timeout} from "../../../../contracts/proto/Channel.sol";
import {
IIBCChannelUpgrade, IIBCChannelUpgradeBase
} from "../../../../contracts/core/04-channel/IIBCChannelUpgrade.sol";
import {IIBCHandler} from "../../../../contracts/core/25-handler/IIBCHandler.sol";
import {IBCMockApp} from "../../../../contracts/apps/mock/IBCMockApp.sol";
import {IBCChannelUpgradableModuleBase} from "./IBCChannelUpgradableModule.sol";
import {IBCAppBase} from "../../../../contracts/apps/commons/IBCAppBase.sol";
import {UpgradeFields, Timeout} from "../../proto/Channel.sol";
import {IIBCChannelUpgradeBase} from "../../core/04-channel/IIBCChannelUpgrade.sol";
import {IIBCHandler} from "../../core/25-handler/IIBCHandler.sol";
import {IBCMockApp} from "./IBCMockApp.sol";
import {IBCChannelUpgradableModuleBase} from "../commons/IBCChannelUpgradableModule.sol";
import {IBCAppBase} from "../commons/IBCAppBase.sol";

contract TestIBCChannelUpgradableMockApp is IBCMockApp, IBCChannelUpgradableModuleBase {
contract IBCChannelUpgradableMockApp is IBCMockApp, IBCChannelUpgradableModuleBase {
constructor(IIBCHandler ibcHandler_) IBCMockApp(ibcHandler_) {}

function supportsInterface(bytes4 interfaceId) public view virtual override(IBCChannelUpgradableModuleBase, IBCAppBase) returns (bool) {
return
super.supportsInterface(interfaceId) || interfaceId == this.proposeAndInitUpgrade.selector;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId)
public
view
virtual
override(IBCChannelUpgradableModuleBase, IBCAppBase)
returns (bool)
{
return super.supportsInterface(interfaceId) || interfaceId == this.proposeAndInitUpgrade.selector;
}

/**
* @dev Propose upgrade and perform chanUpgradeInit.
*/
function proposeAndInitUpgrade(
string calldata portId,
string calldata channelId,
Expand Down
10 changes: 6 additions & 4 deletions tests/foundry/src/ICS04Upgrade.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ import {LocalhostClientLib} from "../../../contracts/clients/09-localhost/Localh
import {LocalhostHelper} from "../../../contracts/clients/09-localhost/LocalhostHelper.sol";
import {IIBCChannelRecvPacket, IIBCChannelAcknowledgePacket} from "../../../contracts/core/04-channel/IIBCChannel.sol";
import {IIBCChannelUpgradeBase} from "../../../contracts/core/04-channel/IIBCChannelUpgrade.sol";
import {IBCChannelUpgradableMockApp} from "../../../contracts/apps/mock/IBCChannelUpgradableMockApp.sol";
import {IIBCHostErrors} from "../../../contracts/core/24-host/IIBCHostErrors.sol";
import {TestIBCChannelUpgradableMockApp} from "./helpers/TestIBCChannelUpgradableMockApp.t.sol";
import {TestIBCChannelUpgradableMockAppInconsistentVersions} from "./helpers/TestIBCChannelUpgradableMockAppInconsistentVersions.t.sol";
import {ICS04UpgradeTestHelper} from "./helpers/ICS04UpgradeTestHelper.t.sol";
import {ICS04PacketEventTestHelper} from "./helpers/ICS04PacketTestHelper.t.sol";
import {IIBCChannelUpgradableModule} from "./helpers/IBCChannelUpgradableModule.sol";
import {
IIBCChannelUpgradableModule
} from "../../../contracts/apps/commons/IBCChannelUpgradableModule.sol";
import {IBCMockLib} from "../../../contracts/apps/mock/IBCMockLib.sol";
import {IBCMockApp} from "../../../contracts/apps/mock/IBCMockApp.sol";

Expand All @@ -26,7 +28,7 @@ contract TestICS04Upgrade is ICS04UpgradeTestHelper, ICS04PacketEventTestHelper
string internal constant MOCK_APP_VERSION_2 = "mockapp-2";

TestableIBCHandler ibcHandler;
TestIBCChannelUpgradableMockApp mockApp;
IBCChannelUpgradableMockApp mockApp;
TestIBCChannelUpgradableMockAppInconsistentVersions maliciousMockApp;

struct ChannelInfo {
Expand All @@ -37,7 +39,7 @@ contract TestICS04Upgrade is ICS04UpgradeTestHelper, ICS04PacketEventTestHelper

function setUp() public {
ibcHandler = defaultIBCHandler();
mockApp = new TestIBCChannelUpgradableMockApp(ibcHandler);
mockApp = new IBCChannelUpgradableMockApp(ibcHandler);
maliciousMockApp = new TestIBCChannelUpgradableMockAppInconsistentVersions(ibcHandler);
ibcHandler.bindPort(MOCK_APP_PORT, mockApp);
ibcHandler.registerLocalhostClient();
Expand Down
12 changes: 5 additions & 7 deletions tests/foundry/src/ICS04UpgradeApp.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@ pragma solidity ^0.8.20;

import "./helpers/IBCTestHelper.t.sol";
import {Vm} from "forge-std/Test.sol";
import {Upgrade, UpgradeFields, Timeout} from "../../../contracts/proto/Channel.sol";
import {LocalhostClientLib} from "../../../contracts/clients/09-localhost/LocalhostClient.sol";
import {UpgradeFields, Timeout} from "../../../contracts/proto/Channel.sol";
import {LocalhostHelper} from "../../../contracts/clients/09-localhost/LocalhostHelper.sol";
import {IIBCChannelUpgrade} from "../../../contracts/core/04-channel/IIBCChannelUpgrade.sol";
import {TestIBCChannelUpgradableMockApp} from "./helpers/TestIBCChannelUpgradableMockApp.t.sol";
import {
IIBCChannelUpgradableModule, IIBCChannelUpgradableModuleErrors
} from "./helpers/IBCChannelUpgradableModule.sol";
} from "../../../contracts/apps/commons/IBCChannelUpgradableModule.sol";
import {IBCChannelUpgradableMockApp} from "../../../contracts/apps/mock/IBCChannelUpgradableMockApp.sol";
import {ICS04UpgradeTestHelper} from "./helpers/ICS04UpgradeTestHelper.t.sol";

contract TestICS04UpgradeApp is ICS04UpgradeTestHelper {
Expand All @@ -21,7 +19,7 @@ contract TestICS04UpgradeApp is ICS04UpgradeTestHelper {
string internal constant MOCK_APP_VERSION_2 = "mockapp-2";

TestableIBCHandler ibcHandler;
TestIBCChannelUpgradableMockApp mockApp;
IBCChannelUpgradableMockApp mockApp;

struct ChannelInfo {
string connectionId;
Expand All @@ -31,7 +29,7 @@ contract TestICS04UpgradeApp is ICS04UpgradeTestHelper {

function setUp() public {
ibcHandler = defaultIBCHandler();
mockApp = new TestIBCChannelUpgradableMockApp(ibcHandler);
mockApp = new IBCChannelUpgradableMockApp(ibcHandler);
ibcHandler.bindPort(MOCK_APP_PORT, mockApp);
ibcHandler.registerLocalhostClient();
ibcHandler.createLocalhostClient();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ pragma solidity ^0.8.20;

import {UpgradeFields} from "../../../../contracts/proto/Channel.sol";
import {TestableIBCHandler} from "./TestableIBCHandler.t.sol";
import {TestIBCChannelUpgradableMockApp} from "./TestIBCChannelUpgradableMockApp.t.sol";
import {IBCChannelUpgradableMockApp} from "../../../../contracts/apps/mock/IBCChannelUpgradableMockApp.sol";

contract TestIBCChannelUpgradableMockAppInconsistentVersions is TestIBCChannelUpgradableMockApp {
constructor(TestableIBCHandler _ibcHandler) TestIBCChannelUpgradableMockApp(_ibcHandler) {}
contract TestIBCChannelUpgradableMockAppInconsistentVersions is IBCChannelUpgradableMockApp {
constructor(TestableIBCHandler _ibcHandler) IBCChannelUpgradableMockApp(_ibcHandler) {}

function onChanUpgradeInit(
string calldata portId,
Expand Down