Skip to content
Prev Previous commit
Next Next commit
add ERC-165 support check to bindPort
Signed-off-by: Jun Kimura <[email protected]>
  • Loading branch information
bluele committed Jul 13, 2024
commit 402dedbfc3faa1c697da8f3019f2975633f58322
20 changes: 10 additions & 10 deletions .gas-snapshot
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
IBCMockAppTest:testHandshake() (gas: 4420576)
IBCMockAppTest:testHandshakeBetweenDifferentPorts() (gas: 3337764)
IBCMockAppTest:testHandshakeBetweenDifferentPorts() (gas: 3339589)
IBCMockAppTest:testPacketRelay() (gas: 13935831)
IBCMockAppTest:testPacketTimeout() (gas: 4279259)
IBCTest:testBenchmarkCreateMockClient() (gas: 233366)
Expand All @@ -8,13 +8,13 @@ IBCTest:testBenchmarkRecvPacket() (gas: 158888)
IBCTest:testBenchmarkSendPacket() (gas: 128432)
IBCTest:testBenchmarkUpdateMockClient() (gas: 160229)
IBCTest:testToUint128((uint64,uint64)) (runs: 256, μ: 947, ~: 947)
TestICS02:testCreateClient() (gas: 36540920)
TestICS02:testInvalidCreateClient() (gas: 36438088)
TestICS02:testInvalidUpdateClient() (gas: 36437047)
TestICS02:testRegisterClient() (gas: 36092713)
TestICS02:testRegisterClientDuplicatedClientType() (gas: 36078022)
TestICS02:testRegisterClientInvalidClientType() (gas: 36107483)
TestICS02:testUpdateClient() (gas: 36605247)
TestICS02:testCreateClient() (gas: 36598021)
TestICS02:testInvalidCreateClient() (gas: 36495138)
TestICS02:testInvalidUpdateClient() (gas: 36494148)
TestICS02:testRegisterClient() (gas: 36149814)
TestICS02:testRegisterClientDuplicatedClientType() (gas: 36135123)
TestICS02:testRegisterClientInvalidClientType() (gas: 36164584)
TestICS02:testUpdateClient() (gas: 36662348)
TestICS03Handshake:testConnOpenAck() (gas: 1858230)
TestICS03Handshake:testConnOpenConfirm() (gas: 2054143)
TestICS03Handshake:testConnOpenInit() (gas: 1429838)
Expand All @@ -29,7 +29,7 @@ TestICS03Version:testIsSupportedVersion() (gas: 7864)
TestICS03Version:testPickVersion() (gas: 25327)
TestICS03Version:testVerifyProposedVersion() (gas: 11777)
TestICS03Version:testVerifySupportedFeature() (gas: 4153)
TestICS04Handshake:testBindPort() (gas: 137001)
TestICS04Handshake:testBindPort() (gas: 429639)
TestICS04Handshake:testChanClose() (gas: 12938942)
TestICS04Handshake:testChanOpenAck() (gas: 3459492)
TestICS04Handshake:testChanOpenConfirm() (gas: 3770761)
Expand All @@ -54,7 +54,7 @@ TestICS04Upgrade:testUpgradeCrossingHelloIncompatibleProposals() (gas: 4434816)
TestICS04Upgrade:testUpgradeFull() (gas: 57784292)
TestICS04Upgrade:testUpgradeInit() (gas: 3071724)
TestICS04Upgrade:testUpgradeNoChanges() (gas: 2473090)
TestICS04Upgrade:testUpgradeNotUpgradableModule() (gas: 3646785)
TestICS04Upgrade:testUpgradeNotUpgradableModule() (gas: 3648610)
TestICS04Upgrade:testUpgradeOutOfSync() (gas: 3904136)
TestICS04Upgrade:testUpgradeRelaySuccessAtCounterpartyFlushComplete() (gas: 5230985)
TestICS04Upgrade:testUpgradeRelaySuccessAtFlushing() (gas: 5604194)
Expand Down
15 changes: 10 additions & 5 deletions contracts/core/24-host/IBCHostConfigurator.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.20;

import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import {IBCClientLib} from "../02-client/IBCClientLib.sol";
import {ILightClient} from "../02-client/ILightClient.sol";
import {IBCModuleManager} from "../26-router/IBCModuleManager.sol";
Expand All @@ -27,16 +28,20 @@ abstract contract IBCHostConfigurator is IIBCHostConfigurator, IBCModuleManager
clientRegistry[clientType] = address(client);
}

function _bindPort(string calldata portId, IIBCModule moduleAddress) internal virtual {
function _bindPort(string calldata portId, IIBCModule module) internal virtual {
address moduleAddress = address(module);
if (!validatePortIdentifier(bytes(portId))) {
revert IBCHostInvalidPortIdentifier(portId);
}
if (address(moduleAddress) == address(0) || address(moduleAddress) == address(this)) {
revert IBCHostInvalidModuleAddress(address(moduleAddress));
if (moduleAddress == address(0) || moduleAddress == address(this)) {
revert IBCHostInvalidModuleAddress(moduleAddress);
}
if (!moduleAddress.supportsInterface(type(IIBCModule).interfaceId)) {
if (!ERC165Checker.supportsERC165(moduleAddress)) {
revert IBCHostModuleDoesNotSupportERC165();
}
if (!ERC165Checker.supportsERC165InterfaceUnchecked(moduleAddress, type(IIBCModule).interfaceId)) {
revert IBCHostModuleDoesNotSupportIIBCModule(type(IIBCModule).interfaceId);
}
claimPortCapability(portId, address(moduleAddress));
claimPortCapability(portId, moduleAddress);
}
}
2 changes: 2 additions & 0 deletions contracts/core/24-host/IIBCHostErrors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ interface IIBCHostErrors {
/// @param channelId channel identifier
error IBCHostModuleChannelNotFound(string portId, string channelId);

error IBCHostModuleDoesNotSupportERC165();

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

Expand Down
32 changes: 27 additions & 5 deletions tests/foundry/src/ICS04Handshake.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ pragma solidity ^0.8.20;
import "../../../contracts/apps/mock/IBCMockApp.sol";
import "./helpers/ICS03TestHelper.t.sol";
import "./helpers/ICS04HandshakeTestHelper.t.sol";
import {AppBase} from "../../../contracts/apps/commons/IBCAppBase.sol";
import {IIBCHostErrors} from "../../../contracts/core/24-host/IIBCHostErrors.sol";

contract DummyApp is AppBase {
address handler;
constructor(address _handler) {
handler = _handler;
}

function ibcAddress() public view override returns (address) {
return handler;
}
}

contract TestICS04Handshake is ICS03TestHelper, ICS04HandshakeMockClientTestHelper {
TestableIBCHandler handler;
Expand All @@ -30,17 +43,26 @@ contract TestICS04Handshake is ICS03TestHelper, ICS04HandshakeMockClientTestHelp
handler.getIBCModuleByPort("portidtwo");

// must be failed if the port is already binded
vm.expectRevert();
vm.expectRevert(abi.encodeWithSelector(IIBCHostErrors.IBCHostPortCapabilityAlreadyClaimed.selector, "portidone"));
handler.bindPort("portidone", mockApp);
// must be failed if the module does not support IIBCModule
vm.expectRevert();
// must be failed if the module does not implement ERC-165
vm.expectRevert(abi.encodeWithSelector(IIBCHostErrors.IBCHostModuleDoesNotSupportERC165.selector));
handler.bindPort("portidtwo", IIBCModule(address(0x01)));
// must be failed the module does not support IIBCModule
address dummyApp = address(new DummyApp(address(handler)));
vm.expectRevert(abi.encodeWithSelector(IIBCHostErrors.IBCHostModuleDoesNotSupportIIBCModule.selector, type(IIBCModule).interfaceId));
handler.bindPort("portidtwo", IIBCModule(dummyApp));
// must be failed if the port is empty
vm.expectRevert();
vm.expectRevert(abi.encodeWithSelector(IIBCHostErrors.IBCHostInvalidPortIdentifier.selector, ""));
handler.bindPort("", IIBCModule(address(0x01)));
// must be failed if the module address is empty
vm.expectRevert();
vm.expectRevert(abi.encodeWithSelector(IIBCHostErrors.IBCHostInvalidModuleAddress.selector, address(0)));
handler.bindPort("portidtwo", IIBCModule(address(0)));
// must be failed if the module address is the host address
vm.expectRevert(abi.encodeWithSelector(IIBCHostErrors.IBCHostInvalidModuleAddress.selector, address(handler)));
handler.bindPort("portidtwo", IIBCModule(address(handler)));
// must be succeed if the module is valid
handler.bindPort("portidtwo", mockApp);
}

function testChanOpenInit() public {
Expand Down