Skip to content
Next Next commit
implement ERC-165 for IBCModule
Signed-off-by: Jun Kimura <[email protected]>
  • Loading branch information
bluele committed Jul 13, 2024
commit 9cd01891045984c7028d020196ad4caf38df3fc8
92 changes: 46 additions & 46 deletions .gas-snapshot
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
IBCMockAppTest:testHandshake() (gas: 4420488)
IBCMockAppTest:testHandshakeBetweenDifferentPorts() (gas: 3334373)
IBCMockAppTest:testPacketRelay() (gas: 13935239)
IBCMockAppTest:testPacketTimeout() (gas: 4279263)
IBCMockAppTest:testHandshake() (gas: 4420576)
IBCMockAppTest:testHandshakeBetweenDifferentPorts() (gas: 3337764)
IBCMockAppTest:testPacketRelay() (gas: 13935831)
IBCMockAppTest:testPacketTimeout() (gas: 4279259)
IBCTest:testBenchmarkCreateMockClient() (gas: 233366)
IBCTest:testBenchmarkLCUpdateMockClient() (gas: 62005)
IBCTest:testBenchmarkRecvPacket() (gas: 158870)
IBCTest:testBenchmarkRecvPacket() (gas: 158888)
IBCTest:testBenchmarkSendPacket() (gas: 128432)
IBCTest:testBenchmarkUpdateMockClient() (gas: 160229)
IBCTest:testToUint128((uint64,uint64)) (runs: 256, μ: 947, ~: 947)
TestICS02:testCreateClient() (gas: 36540928)
TestICS02:testInvalidCreateClient() (gas: 36438147)
TestICS02:testInvalidUpdateClient() (gas: 36437055)
TestICS02:testRegisterClient() (gas: 36092721)
TestICS02:testRegisterClientDuplicatedClientType() (gas: 36078030)
TestICS02:testRegisterClientInvalidClientType() (gas: 36107491)
TestICS02:testUpdateClient() (gas: 36605255)
TestICS02:testCreateClient() (gas: 36596358)
TestICS02:testInvalidCreateClient() (gas: 36493526)
TestICS02:testInvalidUpdateClient() (gas: 36492485)
TestICS02:testRegisterClient() (gas: 36148151)
TestICS02:testRegisterClientDuplicatedClientType() (gas: 36133460)
TestICS02:testRegisterClientInvalidClientType() (gas: 36162921)
TestICS02:testUpdateClient() (gas: 36660685)
TestICS03Handshake:testConnOpenAck() (gas: 1858230)
TestICS03Handshake:testConnOpenConfirm() (gas: 2054143)
TestICS03Handshake:testConnOpenInit() (gas: 1429838)
Expand All @@ -29,43 +29,43 @@ TestICS03Version:testIsSupportedVersion() (gas: 7864)
TestICS03Version:testPickVersion() (gas: 25327)
TestICS03Version:testVerifyProposedVersion() (gas: 11777)
TestICS03Version:testVerifySupportedFeature() (gas: 4153)
TestICS04Handshake:testBindPort() (gas: 124350)
TestICS04Handshake:testChanClose() (gas: 12938854)
TestICS04Handshake:testChanOpenAck() (gas: 3459404)
TestICS04Handshake:testChanOpenConfirm() (gas: 3770673)
TestICS04Handshake:testChanOpenInit() (gas: 2543524)
TestICS04Handshake:testChanOpenTry() (gas: 3099898)
TestICS04Handshake:testInvalidChanOpenAck() (gas: 2439749)
TestICS04Handshake:testInvalidChanOpenConfirm() (gas: 2517338)
TestICS04Handshake:testBindPort() (gas: 128408)
TestICS04Handshake:testChanClose() (gas: 12938942)
TestICS04Handshake:testChanOpenAck() (gas: 3459492)
TestICS04Handshake:testChanOpenConfirm() (gas: 3770761)
TestICS04Handshake:testChanOpenInit() (gas: 2543590)
TestICS04Handshake:testChanOpenTry() (gas: 3099942)
TestICS04Handshake:testInvalidChanOpenAck() (gas: 2439771)
TestICS04Handshake:testInvalidChanOpenConfirm() (gas: 2517382)
TestICS04Handshake:testInvalidChanOpenInit() (gas: 1760558)
TestICS04Handshake:testInvalidChanOpenTry() (gas: 1775528)
TestICS04Packet:testAcknowledgementPacket() (gas: 3351116)
TestICS04Packet:testInvalidSendPacket() (gas: 3551583)
TestICS04Packet:testRecvPacket() (gas: 10996942)
TestICS04Packet:testRecvPacketTimeoutHeight() (gas: 3259727)
TestICS04Packet:testRecvPacketTimeoutTimestamp() (gas: 3279103)
TestICS04Packet:testSendPacket() (gas: 6412442)
TestICS04Packet:testTimeoutOnClose() (gas: 3553289)
TestICS04Upgrade:testUpgradeAuthorityCancel() (gas: 46742335)
TestICS04Upgrade:testUpgradeCannotCancelWithOldErrorReceipt() (gas: 3456630)
TestICS04Upgrade:testUpgradeCannotRecvNextUpgradePacket() (gas: 5266005)
TestICS04Upgrade:testUpgradeCounterpartyAdvanceNextSequenceBeforeOpen() (gas: 5236258)
TestICS04Upgrade:testUpgradeCrossingHelloIncompatibleProposals() (gas: 4407259)
TestICS04Upgrade:testUpgradeFull() (gas: 57784728)
TestICS04Upgrade:testUpgradeInit() (gas: 3069408)
TestICS04Upgrade:testUpgradeNoChanges() (gas: 2471936)
TestICS04Upgrade:testUpgradeOutOfSync() (gas: 3903220)
TestICS04Upgrade:testUpgradeRelaySuccessAtCounterpartyFlushComplete() (gas: 5237770)
TestICS04Upgrade:testUpgradeRelaySuccessAtFlushing() (gas: 5610957)
TestICS04Upgrade:testUpgradeSendPacketFailAtFlushingOrFlushComplete() (gas: 4071025)
TestICS04Upgrade:testUpgradeTimeoutAbortAck() (gas: 17694261)
TestICS04Upgrade:testUpgradeTimeoutAbortConfirm() (gas: 21333518)
TestICS04Upgrade:testUpgradeTimeoutUpgrade() (gas: 71049040)
TestICS04Upgrade:testUpgradeToOrdered() (gas: 56509529)
TestICS04Upgrade:testUpgradeToUnordered() (gas: 45113829)
TestICS04Packet:testAcknowledgementPacket() (gas: 3351204)
TestICS04Packet:testInvalidSendPacket() (gas: 3551671)
TestICS04Packet:testRecvPacket() (gas: 10997558)
TestICS04Packet:testRecvPacketTimeoutHeight() (gas: 3259769)
TestICS04Packet:testRecvPacketTimeoutTimestamp() (gas: 3279145)
TestICS04Packet:testSendPacket() (gas: 6411842)
TestICS04Packet:testTimeoutOnClose() (gas: 3553375)
TestICS04Upgrade:testUpgradeAuthorityCancel() (gas: 46736852)
TestICS04Upgrade:testUpgradeCannotCancelWithOldErrorReceipt() (gas: 3456618)
TestICS04Upgrade:testUpgradeCannotRecvNextUpgradePacket() (gas: 5264735)
TestICS04Upgrade:testUpgradeCounterpartyAdvanceNextSequenceBeforeOpen() (gas: 5234977)
TestICS04Upgrade:testUpgradeCrossingHelloIncompatibleProposals() (gas: 4406999)
TestICS04Upgrade:testUpgradeFull() (gas: 57771943)
TestICS04Upgrade:testUpgradeInit() (gas: 3069201)
TestICS04Upgrade:testUpgradeNoChanges() (gas: 2471837)
TestICS04Upgrade:testUpgradeOutOfSync() (gas: 3903101)
TestICS04Upgrade:testUpgradeRelaySuccessAtCounterpartyFlushComplete() (gas: 5236500)
TestICS04Upgrade:testUpgradeRelaySuccessAtFlushing() (gas: 5609709)
TestICS04Upgrade:testUpgradeSendPacketFailAtFlushingOrFlushComplete() (gas: 4070583)
TestICS04Upgrade:testUpgradeTimeoutAbortAck() (gas: 17691838)
TestICS04Upgrade:testUpgradeTimeoutAbortConfirm() (gas: 21328699)
TestICS04Upgrade:testUpgradeTimeoutUpgrade() (gas: 71035138)
TestICS04Upgrade:testUpgradeToOrdered() (gas: 56500423)
TestICS04Upgrade:testUpgradeToUnordered() (gas: 45106369)
TestICS04UpgradeApp:testUpgradeAuthorizationChanneNotFound() (gas: 61690)
TestICS04UpgradeApp:testUpgradeAuthorizationRePropose() (gas: 2565532)
TestICS04UpgradeApp:testUpgradeAuthorizationRemove() (gas: 2473992)
TestICS04UpgradeApp:testUpgradeAuthorizationRePropose() (gas: 2565379)
TestICS04UpgradeApp:testUpgradeAuthorizationRemove() (gas: 2473938)
TestICS20:testAddressToHex(address) (runs: 256, μ: 22726, ~: 22867)
TestICS20:testHexToAddress(string) (runs: 256, μ: 4776, ~: 4734)
TestICS20:testIsEscapedString() (gas: 48979)
Expand Down
19 changes: 17 additions & 2 deletions contracts/apps/commons/IBCAppBase.sol
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.20;

import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";
import {Packet} from "../../core/04-channel/IIBCChannel.sol";
import {IIBCModule} from "../../core/26-router/IIBCModule.sol";
import {IIBCModuleErrors} from "../../core/26-router/IIBCModuleErrors.sol";

abstract contract AppBase is Context, IIBCModuleErrors {
abstract contract AppBase is IERC165, Context, IIBCModuleErrors {
/**
* @dev Throws if called by any account other than the IBC contract.
*/
Expand All @@ -28,6 +29,16 @@ abstract contract AppBase is Context, IIBCModuleErrors {
revert IBCModuleInvalidSender(_msgSender());
}
}

/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId || interfaceId == this.ibcAddress.selector;
}
}

/**
Expand Down Expand Up @@ -113,5 +124,9 @@ abstract contract IBCAppBase is AppBase, IIBCModule {
*
* NOTE: You should apply an `onlyIBC` modifier to the function if a derived contract overrides it.
*/
function onTimeoutPacket(Packet calldata, address relayer) external virtual onlyIBC {}
function onTimeoutPacket(Packet calldata, address relayer) external virtual override onlyIBC {}

function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, AppBase) returns (bool) {
return interfaceId == type(IIBCModule).interfaceId || super.supportsInterface(interfaceId);
}
}
3 changes: 3 additions & 0 deletions contracts/core/24-host/IBCHostConfigurator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ abstract contract IBCHostConfigurator is IIBCHostConfigurator, IBCModuleManager
if (address(moduleAddress) == address(0) || address(moduleAddress) == address(this)) {
revert IBCHostInvalidModuleAddress(address(moduleAddress));
}
if (!moduleAddress.supportsInterface(type(IIBCModule).interfaceId)) {
revert IBCHostModuleDoesNotImplementIIBCModule(type(IIBCModule).interfaceId);
}
claimPortCapability(portId, address(moduleAddress));
}
}
3 changes: 3 additions & 0 deletions contracts/core/24-host/IIBCHostErrors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ interface IIBCHostErrors {
/// @param channelId channel identifier
error IBCHostModuleChannelNotFound(string portId, string channelId);

/// @param interfaceId expected interface identifier
error IBCHostModuleDoesNotImplementIIBCModule(bytes4 interfaceId);

/// @param portId port identifier
error IBCHostPortCapabilityAlreadyClaimed(string portId);

Expand Down
12 changes: 8 additions & 4 deletions contracts/core/26-router/IIBCModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ pragma solidity ^0.8.20;

import {Channel, ChannelCounterparty} from "../../proto/Channel.sol";
import {Packet} from "../04-channel/IIBCChannel.sol";

// IIBCModule defines an interface that implements all the callbacks
// that modules must define as specified in ICS-26
interface IIBCModule {
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

/**
* @notice IIBCModule is an interface that defines all the callbacks that modules must define as specified in ICS-26
* @dev An IBC module must implement this interface and register itself with the IBCModuleManager
* IERC165's `supportsInterface` must return true for the interface ID of this interface, and the interface ID of IIBCModuleUpgrade if the module supports the channel upgrade
*/
interface IIBCModule is IERC165 {
struct MsgOnChanOpenInit {
Channel.Order order;
string[] connectionHops;
Expand Down
7 changes: 7 additions & 0 deletions tests/foundry/src/helpers/IBCChannelUpgradableModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,13 @@ abstract contract IBCChannelUpgradableModuleBase is
delete allowedTransitions[portId][channelId][upgradeSequence];
}

function supportsInterface(bytes4 interfaceId) public view virtual override(AppBase) returns (bool) {
return
interfaceId == type(IIBCModuleUpgrade).interfaceId ||
interfaceId == type(IIBCChannelUpgradableModule).interfaceId ||
super.supportsInterface(interfaceId);
}

// ------------------- Internal Functions ------------------- //

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@ import {
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";

contract TestIBCChannelUpgradableMockApp 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;
}

function proposeAndInitUpgrade(
string calldata portId,
string calldata channelId,
Expand Down