diff --git a/app/scripts/abi.sh b/app/scripts/abi.sh index 4a92977c63..824915972f 100644 --- a/app/scripts/abi.sh +++ b/app/scripts/abi.sh @@ -8,10 +8,10 @@ nix build .#evm-contracts --print-build-logs IBC_HANDLER=$(jq --slurp 'map(.abi) | add' \ result/out/IBCClient.sol/IBCClient.json \ - result/out/IBCPacket.sol/IBCPacket.json \ - result/out/IBCConnection.sol/IBCConnection.json \ + result/out/IBCPacket.sol/IBCPacketImpl.json \ + result/out/IBCConnection.sol/IBCConnectionImpl.json \ result/out/OwnableIBCHandler.sol/OwnableIBCHandler.json \ - result/out/IBCChannelHandshake.sol/IBCChannelHandshake.json) + result/out/IBCChannel.sol/IBCChannelImpl.json) echo "export const ibcHandlerAbi = ${IBC_HANDLER}" >| app/src/lib/abi/ibc-handler.ts diff --git a/evm/ARCHITECTURE.md b/evm/ARCHITECTURE.md index 7d4e05e4d8..5b6373f6a9 100644 --- a/evm/ARCHITECTURE.md +++ b/evm/ARCHITECTURE.md @@ -67,7 +67,7 @@ sequenceDiagram ``` -To relax the contract size limit of ethereum, each ICS implementation is split into [IBCClient](contracts/core/02-client/IBCClient.sol), [IBCConnection](contracts/core/03-connection/IBCConnection.sol), [IBCChannel](contracts/core/04-channel/IBCChannelHandshake.sol), [IBCPacket](contracts/core/04-channel/IBCPacket.sol), and [IBCHandler](contracts/core/25-handler/IBCHandler.sol) contracts, as shown in the above figure. +To relax the contract size limit of ethereum, each ICS implementation is split into [IBCClient](contracts/core/02-client/IBCClient.sol), [IBCConnection](contracts/core/03-connection/IBCConnection.sol), [IBCChannel](contracts/core/04-channel/IBCChannel.sol), [IBCPacket](contracts/core/04-channel/IBCPacket.sol), and [IBCHandler](contracts/core/25-handler/IBCHandler.sol) contracts, as shown in the above figure. In general, such a design causes storage splitting, so it is required to implement unnecessary authentication and accessors for inter-contract calls. diff --git a/evm/contracts/apps/Base.sol b/evm/contracts/apps/Base.sol index 71a2fbbc27..38eebde07f 100644 --- a/evm/contracts/apps/Base.sol +++ b/evm/contracts/apps/Base.sol @@ -38,12 +38,11 @@ abstract contract IBCAppBase is IIBCModule { * NOTE: You should apply an `onlyIBC` modifier to the function if a derived contract overrides it. */ function onChanOpenInit( - IbcCoreChannelV1GlobalEnums.Order, - string[] calldata connectionHops, - string calldata portId, - string calldata channelId, - IbcCoreChannelV1Counterparty.Data calldata counterpartyEndpoint, - string calldata version, + IBCChannelOrder ordering, + uint32 connectionId, + uint32 channelId, + IBCChannelCounterparty calldata counterpartyEndpoint, + bytes32 version, address relayer ) external virtual override onlyIBC {} @@ -53,13 +52,12 @@ abstract contract IBCAppBase is IIBCModule { * NOTE: You should apply an `onlyIBC` modifier to the function if a derived contract overrides it. */ function onChanOpenTry( - IbcCoreChannelV1GlobalEnums.Order, - string[] calldata connectionHops, - string calldata portId, - string calldata channelId, - IbcCoreChannelV1Counterparty.Data calldata counterpartyEndpoint, - string calldata version, - string calldata counterpartyVersion, + IBCChannelOrder ordering, + uint32 connectionId, + uint32 channelId, + IBCChannelCounterparty calldata counterpartyEndpoint, + bytes32 version, + bytes32 counterpartyVersion, address relayer ) external virtual override onlyIBC {} @@ -69,10 +67,9 @@ abstract contract IBCAppBase is IIBCModule { * NOTE: You should apply an `onlyIBC` modifier to the function if a derived contract overrides it. */ function onChanOpenAck( - string calldata portId, - string calldata channelId, - string calldata counterpartyChannelId, - string calldata counterpartyVersion, + uint32 channelId, + uint32 counterpartyChannelId, + bytes32 counterpartyVersion, address relayer ) external virtual override onlyIBC {} @@ -82,8 +79,7 @@ abstract contract IBCAppBase is IIBCModule { * NOTE: You should apply an `onlyIBC` modifier to the function if a derived contract overrides it. */ function onChanOpenConfirm( - string calldata portId, - string calldata channelId, + uint32 channelId, address relayer ) external virtual override onlyIBC {} @@ -93,8 +89,7 @@ abstract contract IBCAppBase is IIBCModule { * NOTE: You should apply an `onlyIBC` modifier to the function if a derived contract overrides it. */ function onChanCloseInit( - string calldata portId, - string calldata channelId, + uint32 channelId, address relayer ) external virtual override onlyIBC {} @@ -104,8 +99,7 @@ abstract contract IBCAppBase is IIBCModule { * NOTE: You should apply an `onlyIBC` modifier to the function if a derived contract overrides it. */ function onChanCloseConfirm( - string calldata portId, - string calldata channelId, + uint32 channelId, address relayer ) external virtual override onlyIBC {} @@ -115,7 +109,7 @@ abstract contract IBCAppBase is IIBCModule { * NOTE: You should apply an `onlyIBC` modifier to the function if a derived contract overrides it. */ function onRecvPacket( - IbcCoreChannelV1Packet.Data calldata packet, + IBCPacket calldata packet, address relayer ) external @@ -131,7 +125,7 @@ abstract contract IBCAppBase is IIBCModule { * NOTE: You should apply an `onlyIBC` modifier to the function if a derived contract overrides it. */ function onAcknowledgementPacket( - IbcCoreChannelV1Packet.Data calldata packet, + IBCPacket calldata packet, bytes calldata acknowledgement, address relayer ) external virtual override onlyIBC {} @@ -142,7 +136,7 @@ abstract contract IBCAppBase is IIBCModule { * NOTE: You should apply an `onlyIBC` modifier to the function if a derived contract overrides it. */ function onTimeoutPacket( - IbcCoreChannelV1Packet.Data calldata packet, + IBCPacket calldata packet, address relayer ) external virtual override onlyIBC {} } diff --git a/evm/contracts/clients/CometblsClientV2.sol b/evm/contracts/clients/CometblsClientV2.sol index 27b051f5b8..5193d0078c 100644 --- a/evm/contracts/clients/CometblsClientV2.sol +++ b/evm/contracts/clients/CometblsClientV2.sol @@ -20,7 +20,15 @@ import "../lib/ICS23.sol"; import "./ICS23MembershipVerifier.sol"; import "./Verifier.sol"; -struct OptimizedConsensusState { +struct ClientState { + string chainId; + uint64 trustingPeriod; + uint64 maxClockDrift; + IBCHeight frozenHeight; + IBCHeight latestHeight; +} + +struct ConsensusState { uint64 timestamp; bytes32 appHash; bytes32 nextValidatorsHash; @@ -39,6 +47,8 @@ library CometblsClientLib { error ErrInvalidMisbehaviorHeadersSequence(); error ErrInvalidMisbehavior(); error ErrClientFrozen(); + error ErrChainIdTooLong(); + error ErrInvalidInitialConsensusState(); function isExpired( uint64 headerTime, @@ -82,32 +92,33 @@ library CometblsClientLib { return header; } - function encodeMemory( - UnionIbcLightclientsCometblsV1ClientState.Data memory clientState - ) internal pure returns (bytes memory) { + function encodeMemory(ClientState memory clientState) + internal + pure + returns (bytes memory) + { return abi.encode( - clientState.chain_id, - clientState.trusting_period, - clientState.unbonding_period, - clientState.max_clock_drift, - clientState.frozen_height, - clientState.latest_height + clientState.chainId, + clientState.trustingPeriod, + clientState.maxClockDrift, + clientState.frozenHeight, + clientState.latestHeight ); } function decodeClientState(bytes calldata bz) internal pure - returns (UnionIbcLightclientsCometblsV1ClientState.Data calldata) + returns (ClientState calldata) { - UnionIbcLightclientsCometblsV1ClientState.Data calldata clientState; + ClientState calldata clientState; assembly { clientState := bz.offset } return clientState; } - function encodeMemory(OptimizedConsensusState memory consensusState) + function encodeMemory(ConsensusState memory consensusState) internal pure returns (bytes memory) @@ -122,9 +133,9 @@ library CometblsClientLib { function decodeConsensusState(bytes calldata bz) internal pure - returns (OptimizedConsensusState calldata) + returns (ConsensusState calldata) { - OptimizedConsensusState calldata consensusState; + ConsensusState calldata consensusState; assembly { consensusState := bz.offset } @@ -134,9 +145,9 @@ library CometblsClientLib { function decodeConsensusStateMemory(bytes memory bz) internal pure - returns (OptimizedConsensusState memory) + returns (ConsensusState memory) { - OptimizedConsensusState memory consensusState; + ConsensusState memory consensusState; (uint64 timestamp, bytes32 appHash, bytes32 nextValidatorsHash) = abi.decode(bz, (uint64, bytes32, bytes32)); consensusState.timestamp = timestamp; @@ -145,7 +156,7 @@ library CometblsClientLib { return consensusState; } - function commit(OptimizedConsensusState memory consensusState) + function commit(ConsensusState memory consensusState) internal pure returns (bytes32) @@ -153,9 +164,11 @@ library CometblsClientLib { return keccak256(encodeMemory(consensusState)); } - function commit( - UnionIbcLightclientsCometblsV1ClientState.Data memory clientState - ) internal pure returns (bytes32) { + function commit(ClientState memory clientState) + internal + pure + returns (bytes32) + { return keccak256(encodeMemory(clientState)); } } @@ -168,16 +181,15 @@ contract CometblsClient is PausableUpgradeable { using BytesLib for bytes; - using IBCHeight for IbcCoreClientV1Height.Data; + using IBCHeightLib for *; using CometblsClientLib for *; address private ibcHandler; - mapping(string => UnionIbcLightclientsCometblsV1ClientState.Data) private - clientStates; - mapping(string => mapping(uint128 => OptimizedConsensusState)) private + mapping(uint32 => ClientState) private clientStates; + mapping(uint32 => mapping(uint128 => ConsensusState)) private consensusStates; - mapping(string => mapping(uint128 => ProcessedMoment)) private + mapping(uint32 => mapping(uint128 => ProcessedMoment)) private processedMoments; constructor() { @@ -193,82 +205,74 @@ contract CometblsClient is } function createClient( - string calldata clientId, + uint32 clientId, bytes calldata clientStateBytes, bytes calldata consensusStateBytes - ) - external - override - onlyIBC - returns ( - bytes32 clientStateCommitment, - ConsensusStateUpdate memory update, - bool ok - ) - { - UnionIbcLightclientsCometblsV1ClientState.Data calldata clientState = - clientStateBytes.decodeClientState(); - OptimizedConsensusState calldata consensusState = + ) external override onlyIBC returns (ConsensusStateUpdate memory update) { + ClientState calldata clientState = clientStateBytes.decodeClientState(); + ConsensusState calldata consensusState = consensusStateBytes.decodeConsensusState(); if ( - clientState.latest_height.revision_height == 0 + clientState.latestHeight.revisionHeight == 0 || consensusState.timestamp == 0 ) { - return (clientStateCommitment, update, false); + revert CometblsClientLib.ErrInvalidInitialConsensusState(); } // ChainID can't exceed 31 bytes (ensures its big-endian repr fit in F_r) - if (bytes(clientState.chain_id).length > 31) { - return (clientStateCommitment, update, false); + if (bytes(clientState.chainId).length > 31) { + revert CometblsClientLib.ErrChainIdTooLong(); } clientStates[clientId] = clientState; - uint128 latestHeight = clientState.latest_height.toUint128(); + uint128 latestHeight = clientState.latestHeight.toUint128(); consensusStates[clientId][latestHeight] = consensusState; // Normalize to nanosecond because ibc-go recvPacket expects nanos... processedMoments[clientId][latestHeight] = ProcessedMoment({ timestamp: block.timestamp * 1e9, height: block.number }); - return ( - clientState.commit(), - ConsensusStateUpdate({ - consensusStateCommitment: consensusState.commit(), - height: clientState.latest_height - }), - true - ); + return ConsensusStateUpdate({ + clientStateCommitment: clientState.commit(), + consensusStateCommitment: consensusState.commit(), + height: clientState.latestHeight + }); } function misbehavior( - string calldata clientId, + uint32 clientId, UnionIbcLightclientsCometblsV1Header.Data calldata headerA, UnionIbcLightclientsCometblsV1Header.Data calldata headerB ) public { - UnionIbcLightclientsCometblsV1ClientState.Data storage clientState = - clientStates[clientId]; + ClientState storage clientState = clientStates[clientId]; bool fraud = checkMisbehavior(clientId, clientState, headerA, headerB); if (!fraud) { revert CometblsClientLib.ErrInvalidMisbehavior(); } // Similar to tendermint https://github.com/cosmos/ibc-go/blob/bbdcc8c6e965c8a2f607dfb2b61cd13712dd966a/modules/light-clients/07-tendermint/misbehaviour.go#L19 - clientState.frozen_height = - IbcCoreClientV1Height.Data({revision_number: 0, revision_height: 1}); + clientState.frozenHeight = + IBCHeight({revisionNumber: 0, revisionHeight: 1}); } function checkMisbehavior( - string calldata clientId, - UnionIbcLightclientsCometblsV1ClientState.Data storage clientState, + uint32 clientId, + ClientState storage clientState, UnionIbcLightclientsCometblsV1Header.Data calldata headerA, UnionIbcLightclientsCometblsV1Header.Data calldata headerB ) internal returns (bool) { // Ensures that A >= B to simplify the misbehavior of time violation check - if (!headerA.trusted_height.gte(headerB.trusted_height)) { + if ( + !headerA.trusted_height.convert().gte( + headerB.trusted_height.convert() + ) + ) { revert CometblsClientLib.ErrInvalidMisbehaviorHeadersSequence(); } - OptimizedConsensusState storage consensusStateA = - consensusStates[clientId][headerA.trusted_height.toUint128()]; - OptimizedConsensusState storage consensusStateB = - consensusStates[clientId][headerB.trusted_height.toUint128()]; + ConsensusState storage consensusStateA = consensusStates[clientId][headerA + .trusted_height + .convert().toUint128()]; + ConsensusState storage consensusStateB = consensusStates[clientId][headerB + .trusted_height + .convert().toUint128()]; // Check that the headers would have been accepted in an update (, uint64 untrustedTimestampA,) = @@ -276,7 +280,11 @@ contract CometblsClient is (, uint64 untrustedTimestampB,) = verifyHeader(headerB, consensusStateB, clientState); - if (headerA.trusted_height.eq(headerB.trusted_height)) { + if ( + headerA.trusted_height.convert().eq( + headerB.trusted_height.convert() + ) + ) { bytes32 hashA = keccak256(abi.encode(headerA.signed_header)); bytes32 hashB = keccak256(abi.encode(headerB.signed_header)); if (hashA != hashB) { @@ -295,8 +303,8 @@ contract CometblsClient is function verifyHeader( UnionIbcLightclientsCometblsV1Header.Data calldata header, - OptimizedConsensusState storage consensusState, - UnionIbcLightclientsCometblsV1ClientState.Data storage clientState + ConsensusState storage consensusState, + ClientState storage clientState ) internal returns (uint64, uint64, bytes32) { if (consensusState.timestamp == 0) { revert CometblsClientLib.ErrTrustedConsensusStateNotFound(); @@ -320,13 +328,13 @@ contract CometblsClient is uint64 currentTime = uint64(block.timestamp * 1e9); if ( CometblsClientLib.isExpired( - untrustedTimestamp, clientState.trusting_period, currentTime + untrustedTimestamp, clientState.trustingPeriod, currentTime ) ) { revert CometblsClientLib.ErrHeaderExpired(); } - uint64 maxClockDrift = currentTime + clientState.max_clock_drift; + uint64 maxClockDrift = currentTime + clientState.maxClockDrift; if (untrustedTimestamp >= maxClockDrift) { revert CometblsClientLib.ErrMaxClockDriftExceeded(); @@ -351,7 +359,7 @@ contract CometblsClient is bool ok = internalVerifyZKP( header.zero_knowledge_proof, - clientState.chain_id, + clientState.chainId, trustedValidatorsHash, header.signed_header ); @@ -364,38 +372,32 @@ contract CometblsClient is } function updateClient( - string calldata clientId, + uint32 clientId, bytes calldata clientMessageBytes - ) - external - override - onlyIBC - returns (bytes32, ConsensusStateUpdate[] memory) - { + ) external override onlyIBC returns (ConsensusStateUpdate memory) { UnionIbcLightclientsCometblsV1Header.Data calldata header = clientMessageBytes.decodeHeader(); - UnionIbcLightclientsCometblsV1ClientState.Data storage clientState = - clientStates[clientId]; + ClientState storage clientState = clientStates[clientId]; - if (!clientState.frozen_height.isZero()) { + if (!clientState.frozenHeight.isZero()) { revert CometblsClientLib.ErrClientFrozen(); } - OptimizedConsensusState storage consensusState = - consensusStates[clientId][header.trusted_height.toUint128()]; + ConsensusState storage consensusState = consensusStates[clientId][header + .trusted_height + .convert().toUint128()]; (uint64 untrustedHeightNumber, uint64 untrustedTimestamp,) = verifyHeader(header, consensusState, clientState); // Update states - if (untrustedHeightNumber > clientState.latest_height.revision_height) { - clientState.latest_height.revision_height = untrustedHeightNumber; + if (untrustedHeightNumber > clientState.latestHeight.revisionHeight) { + clientState.latestHeight.revisionHeight = untrustedHeightNumber; } - IbcCoreClientV1Height.Data memory untrustedHeight = - IbcCoreClientV1Height.Data({ - revision_number: header.trusted_height.revision_number, - revision_height: untrustedHeightNumber + IBCHeight memory untrustedHeight = IBCHeight({ + revisionNumber: header.trusted_height.revision_number, + revisionHeight: untrustedHeightNumber }); uint128 untrustedHeightIndex = untrustedHeight.toUint128(); @@ -411,18 +413,16 @@ contract CometblsClient is processed.timestamp = block.timestamp * 1e9; processed.height = block.number; - ConsensusStateUpdate[] memory updates = new ConsensusStateUpdate[](1); - updates[0] = ConsensusStateUpdate({ + return ConsensusStateUpdate({ + clientStateCommitment: clientState.commit(), consensusStateCommitment: consensusState.commit(), height: untrustedHeight }); - - return (clientState.commit(), updates); } function verifyMembership( - string calldata clientId, - IbcCoreClientV1Height.Data calldata height, + uint32 clientId, + IBCHeight calldata height, uint64 delayPeriodTime, uint64 delayPeriodBlocks, bytes calldata proof, @@ -442,8 +442,8 @@ contract CometblsClient is } function verifyNonMembership( - string calldata clientId, - IbcCoreClientV1Height.Data calldata height, + uint32 clientId, + IBCHeight calldata height, uint64 delayPeriodTime, uint64 delayPeriodBlocks, bytes calldata proof, @@ -462,12 +462,12 @@ contract CometblsClient is } function validateDelayPeriod( - string calldata clientId, - IbcCoreClientV1Height.Data calldata height, + uint32 clientId, + IBCHeight calldata height, uint64 delayPeriodTime, uint64 delayPeriodBlocks ) internal view returns (bytes32) { - OptimizedConsensusState storage consensusState = + ConsensusState storage consensusState = consensusStates[clientId][height.toUint128()]; if (consensusState.timestamp == 0) { revert CometblsClientLib.ErrTrustedConsensusStateNotFound(); @@ -487,7 +487,7 @@ contract CometblsClient is return consensusState.appHash; } - function getClientState(string calldata clientId) + function getClientState(uint32 clientId) external view returns (bytes memory) @@ -496,43 +496,34 @@ contract CometblsClient is } function getConsensusState( - string calldata clientId, - IbcCoreClientV1Height.Data calldata height + uint32 clientId, + IBCHeight calldata height ) external view returns (bytes memory) { return consensusStates[clientId][height.toUint128()].encodeMemory(); } function getTimestampAtHeight( - string calldata clientId, - IbcCoreClientV1Height.Data calldata height + uint32 clientId, + IBCHeight calldata height ) external view override returns (uint64) { return consensusStates[clientId][height.toUint128()].timestamp; } - function getLatestHeight(string calldata clientId) + function getLatestHeight(uint32 clientId) external view override - returns (IbcCoreClientV1Height.Data memory) + returns (IBCHeight memory) { - return clientStates[clientId].latest_height; + return clientStates[clientId].latestHeight; } - function isFrozen(string calldata clientId) - external - view - virtual - returns (bool) - { + function isFrozen(uint32 clientId) external view virtual returns (bool) { return isFrozenImpl(clientId); } - function isFrozenImpl(string calldata clientId) - internal - view - returns (bool) - { - return !clientStates[clientId].frozen_height.isZero(); + function isFrozenImpl(uint32 clientId) internal view returns (bool) { + return !clientStates[clientId].frozenHeight.isZero(); } // ZKP VERIFICATION @@ -629,7 +620,7 @@ contract CometblsClient is onlyOwner {} - function _onlyIBC() private view { + function _onlyIBC() internal view { if (msg.sender != ibcHandler) { revert CometblsClientLib.ErrNotIBC(); } diff --git a/evm/contracts/clients/CosmosInCosmosClient.sol b/evm/contracts/clients/CosmosInCosmosClient.sol index 28ef2bad32..1dd25c7e28 100644 --- a/evm/contracts/clients/CosmosInCosmosClient.sol +++ b/evm/contracts/clients/CosmosInCosmosClient.sol @@ -16,10 +16,6 @@ import {IbcLightclientsTendermintV1ConsensusState as TendermintConsensusState} import "../proto/cosmos/ics23/v1/proofs.sol"; import "../proto/tendermint/types/types.sol"; import "../proto/tendermint/types/canonical.sol"; -import { - UnionIbcLightclientsCosmosincosmosV1ClientState as CosmosInCosmosClientState, - UnionIbcLightclientsCosmosincosmosV1Header as CosmosInCosmosHeader -} from "../proto/union/ibc/lightclients/cosmosincosmos/v1/cosmosincosmos.sol"; import {UnionIbcLightclientsCometblsV1ClientState as CometblsClientState} from "../proto/union/ibc/lightclients/cometbls/v1/cometbls.sol"; import "../proto/ibc/lightclients/wasm/v1/wasm.sol"; @@ -27,7 +23,21 @@ import "../lib/ICS23.sol"; import "./ICS23MembershipVerifier.sol"; import {ProcessedMoment} from "../lib/Common.sol"; -struct OptimizedCosmosInCosmosConsensusState { +struct Header { + IBCHeight l1Height; + IBCHeight l2Height; + bytes l2InclusionProof; + bytes l2ConsensusState; +} + +struct ClientState { + string l2ChainId; + uint32 l1ClientId; + uint32 l2ClientId; + IBCHeight latestHeight; +} + +struct ConsensusState { uint64 timestamp; bytes32 appHash; } @@ -38,8 +48,9 @@ library CosmosInCosmosLib { error ErrDelayPeriodNotExpired(); error ErrClientFrozen(); error ErrInvalidL1Proof(); + error ErrInvalidInitialConsensusState(); - function encode(OptimizedCosmosInCosmosConsensusState memory consensusState) + function encode(ConsensusState memory consensusState) internal pure returns (bytes memory) @@ -47,20 +58,20 @@ library CosmosInCosmosLib { return abi.encode(consensusState.timestamp, consensusState.appHash); } - function encode(CosmosInCosmosClientState.Data memory clientState) + function encode(ClientState memory clientState) internal pure returns (bytes memory) { return abi.encode( - clientState.l2_chain_id, - clientState.l1_client_id, - clientState.l2_client_id, - clientState.latest_height + clientState.l2ChainId, + clientState.l1ClientId, + clientState.l2ClientId, + clientState.latestHeight ); } - function commit(OptimizedCosmosInCosmosConsensusState memory consensusState) + function commit(ConsensusState memory consensusState) internal pure returns (bytes32) @@ -68,7 +79,7 @@ library CosmosInCosmosLib { return keccak256(encode(consensusState)); } - function commit(CosmosInCosmosClientState.Data memory clientState) + function commit(ClientState memory clientState) internal pure returns (bytes32) @@ -85,15 +96,15 @@ contract CosmosInCosmosClient is PausableUpgradeable { using BytesLib for bytes; - using IBCHeight for IbcCoreClientV1Height.Data; + using IBCHeightLib for IBCHeight; using CosmosInCosmosLib for *; address private ibcHandler; - mapping(string => CosmosInCosmosClientState.Data) private clientStates; - mapping(string => mapping(uint128 => OptimizedCosmosInCosmosConsensusState)) - private consensusStates; - mapping(string => mapping(uint128 => ProcessedMoment)) private + mapping(uint32 => ClientState) private clientStates; + mapping(uint32 => mapping(uint128 => ConsensusState)) private + consensusStates; + mapping(uint32 => mapping(uint128 => ProcessedMoment)) private processedMoments; constructor() { @@ -109,49 +120,37 @@ contract CosmosInCosmosClient is } function createClient( - string calldata clientId, + uint32 clientId, bytes calldata clientStateBytes, bytes calldata consensusStateBytes - ) - external - override - onlyIBC - returns ( - bytes32 clientStateCommitment, - ConsensusStateUpdate memory update, - bool ok - ) - { - CosmosInCosmosClientState.Data calldata clientState; + ) external override onlyIBC returns (ConsensusStateUpdate memory update) { + ClientState calldata clientState; assembly { clientState := clientStateBytes.offset } - OptimizedCosmosInCosmosConsensusState calldata consensusState; + ConsensusState calldata consensusState; assembly { consensusState := consensusStateBytes.offset } if ( - clientState.latest_height.revision_height == 0 + clientState.latestHeight.revisionHeight == 0 || consensusState.timestamp == 0 ) { - return (clientStateCommitment, update, false); + revert CosmosInCosmosLib.ErrInvalidInitialConsensusState(); } clientStates[clientId] = clientState; - uint128 latestHeight = clientState.latest_height.toUint128(); + uint128 latestHeight = clientState.latestHeight.toUint128(); consensusStates[clientId][latestHeight] = consensusState; // Normalize to nanosecond because ibc-go recvPacket expects nanos... processedMoments[clientId][latestHeight] = ProcessedMoment({ timestamp: block.timestamp * 1e9, height: block.number }); - return ( - clientState.commit(), - ConsensusStateUpdate({ - consensusStateCommitment: consensusState.commit(), - height: clientState.latest_height - }), - true - ); + return ConsensusStateUpdate({ + clientStateCommitment: clientState.commit(), + consensusStateCommitment: consensusState.commit(), + height: clientState.latestHeight + }); } /* @@ -159,49 +158,43 @@ contract CosmosInCosmosClient is * Given an L₂ and L₁ heights (H₂, H₁), we prove that L₂[H₂] ∈ L₁[H₁]. */ function updateClient( - string calldata clientId, + uint32 clientId, bytes calldata clientMessageBytes - ) - external - override - onlyIBC - returns (bytes32, ConsensusStateUpdate[] memory) - { - CosmosInCosmosHeader.Data calldata header; + ) external override onlyIBC returns (ConsensusStateUpdate memory) { + Header calldata header; assembly { header := clientMessageBytes.offset } - CosmosInCosmosClientState.Data memory clientState = - clientStates[clientId]; + ClientState memory clientState = clientStates[clientId]; ILightClient l1Client = - IBCStore(ibcHandler).getClient(clientState.l1_client_id); + IBCStore(ibcHandler).getClient(clientState.l1ClientId); // L₂[H₂] ∈ L₁[H₁] if ( !l1Client.verifyMembership( - clientState.l1_client_id, - header.l1_height, + clientState.l1ClientId, + header.l1Height, 0, 0, - header.l2_inclusion_proof, - bytes(IBCStoreLib.COMMITMENT_PREFIX), + header.l2InclusionProof, + abi.encodePacked(IBCStoreLib.COMMITMENT_PREFIX), IBCCommitment.consensusStatePath( - clientState.l2_client_id, - header.l2_height.revision_number, - header.l2_height.revision_height + clientState.l2ClientId, + header.l2Height.revisionNumber, + header.l2Height.revisionHeight ), - header.l2_consensus_state + header.l2ConsensusState ) ) { revert CosmosInCosmosLib.ErrInvalidL1Proof(); } TendermintConsensusState.Data memory l2ConsensusState = - TendermintConsensusState.decode(header.l2_consensus_state); + TendermintConsensusState.decode(header.l2ConsensusState); - if (header.l2_height.gt(clientState.latest_height)) { - clientState.latest_height = header.l2_height; + if (header.l2Height.gt(clientState.latestHeight)) { + clientState.latestHeight = header.l2Height; } - uint128 l2HeightIndex = header.l2_height.toUint128(); + uint128 l2HeightIndex = header.l2Height.toUint128(); // Cosmos expects nanos... uint64 l2Timestamp = uint64(l2ConsensusState.timestamp.secs) * 1e9 @@ -210,7 +203,7 @@ contract CosmosInCosmosClient is // L₂[H₂] = optimize(S₂) // The default tendermint consensus state is stored as protobuf. // We use ethereum native encoding to make it more efficient. - OptimizedCosmosInCosmosConsensusState storage consensusState = + ConsensusState storage consensusState = consensusStates[clientId][l2HeightIndex]; consensusState.timestamp = l2Timestamp; consensusState.appHash = l2ConsensusState.root.hash.toBytes32(0); @@ -222,18 +215,16 @@ contract CosmosInCosmosClient is processed.height = block.number; // commit(optimize(S₂)) - ConsensusStateUpdate[] memory updates = new ConsensusStateUpdate[](1); - updates[0] = ConsensusStateUpdate({ + return ConsensusStateUpdate({ + clientStateCommitment: clientState.commit(), consensusStateCommitment: consensusState.commit(), - height: header.l2_height + height: header.l2Height }); - - return (clientState.commit(), updates); } function verifyMembership( - string calldata clientId, - IbcCoreClientV1Height.Data calldata height, + uint32 clientId, + IBCHeight calldata height, uint64 delayPeriodTime, uint64 delayPeriodBlocks, bytes calldata proof, @@ -253,8 +244,8 @@ contract CosmosInCosmosClient is } function verifyNonMembership( - string calldata clientId, - IbcCoreClientV1Height.Data calldata height, + uint32 clientId, + IBCHeight calldata height, uint64 delayPeriodTime, uint64 delayPeriodBlocks, bytes calldata proof, @@ -273,12 +264,12 @@ contract CosmosInCosmosClient is } function validateDelayPeriod( - string calldata clientId, - IbcCoreClientV1Height.Data calldata height, + uint32 clientId, + IBCHeight calldata height, uint64 delayPeriodTime, uint64 delayPeriodBlocks ) internal view returns (bytes32) { - OptimizedCosmosInCosmosConsensusState storage consensusState = + ConsensusState storage consensusState = consensusStates[clientId][height.toUint128()]; if (consensusState.timestamp == 0) { revert CosmosInCosmosLib.ErrTrustedConsensusStateNotFound(); @@ -298,7 +289,7 @@ contract CosmosInCosmosClient is return consensusState.appHash; } - function getClientState(string calldata clientId) + function getClientState(uint32 clientId) external view returns (bytes memory) @@ -307,43 +298,34 @@ contract CosmosInCosmosClient is } function getConsensusState( - string calldata clientId, - IbcCoreClientV1Height.Data calldata height + uint32 clientId, + IBCHeight calldata height ) external view returns (bytes memory) { return consensusStates[clientId][height.toUint128()].encode(); } function getTimestampAtHeight( - string calldata clientId, - IbcCoreClientV1Height.Data calldata height + uint32 clientId, + IBCHeight calldata height ) external view override returns (uint64) { return consensusStates[clientId][height.toUint128()].timestamp; } - function getLatestHeight(string calldata clientId) + function getLatestHeight(uint32 clientId) external view override - returns (IbcCoreClientV1Height.Data memory) + returns (IBCHeight memory) { - return clientStates[clientId].latest_height; + return clientStates[clientId].latestHeight; } - function isFrozen(string calldata clientId) - external - view - virtual - returns (bool) - { + function isFrozen(uint32 clientId) external view virtual returns (bool) { return isFrozenImpl(clientId); } - function isFrozenImpl(string calldata clientId) - internal - view - returns (bool) - { - string memory l1ClientId = clientStates[clientId].l1_client_id; + function isFrozenImpl(uint32 clientId) internal view returns (bool) { + uint32 l1ClientId = clientStates[clientId].l1ClientId; return IBCStore(ibcHandler).getClient(l1ClientId).isFrozen(l1ClientId); } @@ -353,7 +335,7 @@ contract CosmosInCosmosClient is onlyOwner {} - function _onlyIBC() private view { + function _onlyIBC() internal view { if (msg.sender != ibcHandler) { revert CosmosInCosmosLib.ErrNotIBC(); } diff --git a/evm/contracts/core/02-client/IBCClient.sol b/evm/contracts/core/02-client/IBCClient.sol index b883e2896d..1dcfca501e 100644 --- a/evm/contracts/core/02-client/IBCClient.sol +++ b/evm/contracts/core/02-client/IBCClient.sol @@ -1,34 +1,30 @@ pragma solidity ^0.8.23; -import "@openzeppelin/utils/Strings.sol"; import "./ILightClient.sol"; import "../25-handler/IBCMsgs.sol"; import "../24-host/IBCStore.sol"; import "../24-host/IBCCommitment.sol"; import "../02-client/IIBCClient.sol"; -import "../../proto/ibc/core/client/v1/client.sol"; library IBCClientLib { - event ClientRegistered(string clientType, address clientAddress); - event ClientCreated(string clientId); - event ClientUpdated(string clientId, IbcCoreClientV1Height.Data height); + event ClientRegistered(bytes32 clientType, address clientAddress); + event ClientCreated(uint32 clientId); + event ClientUpdated(uint32 clientId, IBCHeight height); error ErrClientTypeAlreadyExists(); error ErrClientMustNotBeSelf(); error ErrClientTypeNotFound(); - error ErrFailedToCreateClient(); - error ErrFailedToUpdateClient(); } /** * @dev IBCClient is a contract that implements [ICS-2](https://github.com/cosmos/ibc/tree/main/spec/core/ics-002-client-semantics). */ -contract IBCClient is IBCStore, IIBCClient { +abstract contract IBCClient is IBCStore, IIBCClient { /** * @dev registerClient registers a new client type into the client registry */ function registerClient( - string calldata clientType, + bytes32 clientType, ILightClient client ) external override { if (address(clientRegistry[clientType]) != address(0)) { @@ -38,7 +34,6 @@ contract IBCClient is IBCStore, IIBCClient { revert IBCClientLib.ErrClientMustNotBeSelf(); } clientRegistry[clientType] = address(client); - emit IBCClientLib.ClientRegistered(clientType, address(client)); } @@ -48,37 +43,23 @@ contract IBCClient is IBCStore, IIBCClient { function createClient(IBCMsgs.MsgCreateClient calldata msg_) external override - returns (string memory clientId) + returns (uint32) { address clientImpl = clientRegistry[msg_.clientType]; if (clientImpl == address(0)) { revert IBCClientLib.ErrClientTypeNotFound(); } - clientId = generateClientIdentifier(msg_.clientType); + uint32 clientId = generateClientIdentifier(); clientTypes[clientId] = msg_.clientType; clientImpls[clientId] = clientImpl; - ( - bytes32 clientStateCommitment, - ConsensusStateUpdate memory update, - bool ok - ) = ILightClient(clientImpl).createClient( - clientId, msg_.clientStateBytes, msg_.consensusStateBytes - ); - if (!ok) { - revert IBCClientLib.ErrFailedToCreateClient(); - } - - // update commitments + ConsensusStateUpdate memory update = ILightClient(clientImpl) + .createClient(clientId, msg_.clientStateBytes, msg_.consensusStateBytes); commitments[keccak256(IBCCommitment.clientStatePath(clientId))] = - clientStateCommitment; + update.clientStateCommitment; commitments[IBCCommitment.consensusStateCommitmentKey( - clientId, - update.height.revision_number, - update.height.revision_height + clientId, update.height.revisionNumber, update.height.revisionHeight )] = update.consensusStateCommitment; - emit IBCClientLib.ClientCreated(clientId); - return clientId; } @@ -89,47 +70,23 @@ contract IBCClient is IBCStore, IIBCClient { external override { - if ( - commitments[IBCCommitment.clientStateCommitmentKey(msg_.clientId)] - == bytes32(0) - ) { - revert IBCStoreLib.ErrClientNotFound(); - } - (bytes32 clientStateCommitment, ConsensusStateUpdate[] memory updates) = - getClient(msg_.clientId).updateClient(msg_.clientId, msg_.clientMessage); - uint256 updatesLength = updates.length; - if (updatesLength == 0) { - revert IBCClientLib.ErrFailedToUpdateClient(); - } - - // update commitments + ConsensusStateUpdate memory update = getClientInternal(msg_.clientId) + .updateClient(msg_.clientId, msg_.clientMessage); commitments[keccak256(IBCCommitment.clientStatePath(msg_.clientId))] = - clientStateCommitment; - for (uint256 i; i < updatesLength; i++) { - commitments[IBCCommitment.consensusStateCommitmentKey( - msg_.clientId, - updates[i].height.revision_number, - updates[i].height.revision_height - )] = updates[i].consensusStateCommitment; - emit IBCClientLib.ClientUpdated(msg_.clientId, updates[i].height); - } + update.clientStateCommitment; + commitments[IBCCommitment.consensusStateCommitmentKey( + msg_.clientId, + update.height.revisionNumber, + update.height.revisionHeight + )] = update.consensusStateCommitment; + emit IBCClientLib.ClientUpdated(msg_.clientId, update.height); } - function generateClientIdentifier(string calldata clientType) - private - returns (string memory) - { - uint256 nextClientSequence = - uint256(commitments[nextClientSequencePath]); - - string memory identifier = string( - abi.encodePacked( - clientType, "-", Strings.toString(nextClientSequence) - ) - ); - - commitments[nextClientSequencePath] = bytes32(nextClientSequence + 1); - - return identifier; + function generateClientIdentifier() internal returns (uint32) { + uint32 nextClientSequence = + uint32(uint256(commitments[nextClientSequencePath])); + commitments[nextClientSequencePath] = + bytes32(uint256(nextClientSequence + 1)); + return nextClientSequence; } } diff --git a/evm/contracts/core/02-client/IBCHeight.sol b/evm/contracts/core/02-client/IBCHeight.sol index f6d7cb8d31..7885afbe61 100644 --- a/evm/contracts/core/02-client/IBCHeight.sol +++ b/evm/contracts/core/02-client/IBCHeight.sol @@ -1,89 +1,93 @@ pragma solidity ^0.8.23; import "../../proto/ibc/core/client/v1/client.sol"; +import "../Types.sol"; -library IBCHeight { - function toUint128(IbcCoreClientV1Height.Data memory self) +library IBCHeightLib { + function convert(IbcCoreClientV1Height.Data memory self) internal pure - returns (uint128) + returns (IBCHeight memory) { - return (uint128(self.revision_number) << 64) - | uint128(self.revision_height); + return IBCHeight({ + revisionNumber: self.revision_number, + revisionHeight: self.revision_height + }); + } + + function toUint128(IBCHeight memory self) internal pure returns (uint128) { + return + (uint128(self.revisionNumber) << 64) | uint128(self.revisionHeight); } function fromUint128(uint128 composite) internal pure - returns (IbcCoreClientV1Height.Data memory) + returns (IBCHeight memory) { - return IbcCoreClientV1Height.Data({ - revision_number: uint64(composite >> 64), - revision_height: uint64(composite) + return IBCHeight({ + revisionNumber: uint64(composite >> 64), + revisionHeight: uint64(composite) }); } - function isZero(IbcCoreClientV1Height.Data memory self) - internal - pure - returns (bool) - { - return self.revision_number == 0 && self.revision_height == 0; + function isZero(IBCHeight memory self) internal pure returns (bool) { + return self.revisionNumber == 0 && self.revisionHeight == 0; } function lt( - IbcCoreClientV1Height.Data memory self, - IbcCoreClientV1Height.Data memory other + IBCHeight memory self, + IBCHeight memory other ) internal pure returns (bool) { - return self.revision_number < other.revision_number + return self.revisionNumber < other.revisionNumber || ( - self.revision_number == other.revision_number - && self.revision_height < other.revision_height + self.revisionNumber == other.revisionNumber + && self.revisionHeight < other.revisionHeight ); } function lte( - IbcCoreClientV1Height.Data memory self, - IbcCoreClientV1Height.Data memory other + IBCHeight memory self, + IBCHeight memory other ) internal pure returns (bool) { - return self.revision_number < other.revision_number + return self.revisionNumber < other.revisionNumber || ( - self.revision_number == other.revision_number - && self.revision_height <= other.revision_height + self.revisionNumber == other.revisionNumber + && self.revisionHeight <= other.revisionHeight ); } function eq( - IbcCoreClientV1Height.Data memory self, - IbcCoreClientV1Height.Data memory other + IBCHeight memory self, + IBCHeight memory other ) internal pure returns (bool) { - return self.revision_number == other.revision_number - && self.revision_height == other.revision_height; + return self.revisionNumber == other.revisionNumber + && self.revisionHeight == other.revisionHeight; } function gt( - IbcCoreClientV1Height.Data memory self, - IbcCoreClientV1Height.Data memory other + IBCHeight memory self, + IBCHeight memory other ) internal pure returns (bool) { - return self.revision_number > other.revision_number + return self.revisionNumber > other.revisionNumber || ( - self.revision_number == other.revision_number - && self.revision_height > other.revision_height + self.revisionNumber == other.revisionNumber + && self.revisionHeight > other.revisionHeight ); } function gte( - IbcCoreClientV1Height.Data memory self, - IbcCoreClientV1Height.Data memory other + IBCHeight memory self, + IBCHeight memory other ) internal pure returns (bool) { - return self.revision_number > other.revision_number + return self.revisionNumber > other.revisionNumber || ( - self.revision_number == other.revision_number - && self.revision_height >= other.revision_height + self.revisionNumber == other.revisionNumber + && self.revisionHeight >= other.revisionHeight ); } - function zero() internal pure returns (IbcCoreClientV1Height.Data memory) { + function zero() internal pure returns (IBCHeight memory) { return fromUint128(0); } } diff --git a/evm/contracts/core/02-client/IIBCClient.sol b/evm/contracts/core/02-client/IIBCClient.sol index ac0fc74494..ca355f7356 100644 --- a/evm/contracts/core/02-client/IIBCClient.sol +++ b/evm/contracts/core/02-client/IIBCClient.sol @@ -7,17 +7,14 @@ interface IIBCClient { /** * @dev registerClient registers a new client type into the client registry */ - function registerClient( - string calldata clientType, - ILightClient client - ) external; + function registerClient(bytes32 clientType, ILightClient client) external; /** * @dev createClient creates a new client state and populates it with a given consensus state */ function createClient(IBCMsgs.MsgCreateClient calldata msg_) external - returns (string memory clientId); + returns (uint32 clientId); /** * @dev updateClient updates the consensus state and the state root from a provided header diff --git a/evm/contracts/core/02-client/ILightClient.sol b/evm/contracts/core/02-client/ILightClient.sol index 4e38c762cd..8e07da3cae 100644 --- a/evm/contracts/core/02-client/ILightClient.sol +++ b/evm/contracts/core/02-client/ILightClient.sol @@ -1,12 +1,11 @@ pragma solidity ^0.8.23; -import "../../proto/ibc/core/client/v1/client.sol"; +import "../Types.sol"; struct ConsensusStateUpdate { - // commitment for updated consensusState + bytes32 clientStateCommitment; bytes32 consensusStateCommitment; - // updated height - IbcCoreClientV1Height.Data height; + IBCHeight height; } /** @@ -19,32 +18,26 @@ interface ILightClient { * If succeeded, it returns a commitment for the initial state. */ function createClient( - string calldata clientId, + uint32 clientId, bytes calldata clientStateBytes, bytes calldata consensusStateBytes - ) - external - returns ( - bytes32 clientStateCommitment, - ConsensusStateUpdate memory update, - bool ok - ); + ) external returns (ConsensusStateUpdate memory update); /** * @dev getTimestampAtHeight returns the timestamp of the consensus state at the given height. */ function getTimestampAtHeight( - string calldata clientId, - IbcCoreClientV1Height.Data calldata height + uint32 clientId, + IBCHeight calldata height ) external view returns (uint64); /** * @dev getLatestHeight returns the latest height of the client state corresponding to `clientId`. */ - function getLatestHeight(string calldata clientId) + function getLatestHeight(uint32 clientId) external view - returns (IbcCoreClientV1Height.Data memory); + returns (IBCHeight memory); /** * @dev updateClient updates the client corresponding to `clientId`. @@ -59,22 +52,17 @@ interface ILightClient { * 5. persist the state(s) on the host */ function updateClient( - string calldata clientId, + uint32 clientId, bytes calldata clientMessageBytes - ) - external - returns ( - bytes32 clientStateCommitment, - ConsensusStateUpdate[] memory updates - ); + ) external returns (ConsensusStateUpdate memory update); /** * @dev verifyMembership is a generic proof verification method which verifies a proof of the existence of a value at a given CommitmentPath at the specified height. * The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24). */ function verifyMembership( - string calldata clientId, - IbcCoreClientV1Height.Data calldata height, + uint32 clientId, + IBCHeight calldata height, uint64 delayTimePeriod, uint64 delayBlockPeriod, bytes calldata proof, @@ -88,8 +76,8 @@ interface ILightClient { * The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24). */ function verifyNonMembership( - string calldata clientId, - IbcCoreClientV1Height.Data calldata height, + uint32 clientId, + IBCHeight calldata height, uint64 delayTimePeriod, uint64 delayBlockPeriod, bytes calldata proof, @@ -100,7 +88,7 @@ interface ILightClient { /** * @dev getClientState returns the clientState corresponding to `clientId`. */ - function getClientState(string calldata clientId) + function getClientState(uint32 clientId) external view returns (bytes memory); @@ -109,12 +97,12 @@ interface ILightClient { * @dev getConsensusState returns the consensusState corresponding to `clientId` and `height`. */ function getConsensusState( - string calldata clientId, - IbcCoreClientV1Height.Data calldata height + uint32 clientId, + IBCHeight calldata height ) external view returns (bytes memory); /** * @dev isFrozen returns whether the `clientId` is frozen or not. */ - function isFrozen(string calldata clientId) external view returns (bool); + function isFrozen(uint32 clientId) external view returns (bool); } diff --git a/evm/contracts/core/03-connection/IBCConnection.sol b/evm/contracts/core/03-connection/IBCConnection.sol index 4d0c9a7e8d..d4d96c6abb 100644 --- a/evm/contracts/core/03-connection/IBCConnection.sol +++ b/evm/contracts/core/03-connection/IBCConnection.sol @@ -1,335 +1,41 @@ pragma solidity ^0.8.23; -import "solady/utils/LibString.sol"; -import "@openzeppelin/utils/Strings.sol"; -import "../../proto/ibc/core/client/v1/client.sol"; -import "../../proto/ibc/core/connection/v1/connection.sol"; -import "../25-handler/IBCMsgs.sol"; import "../24-host/IBCStore.sol"; +import "../25-handler/IBCMsgs.sol"; import "../24-host/IBCCommitment.sol"; import "../03-connection/IIBCConnection.sol"; library IBCConnectionLib { event ConnectionOpenInit( - string connectionId, string clientId, string counterpartyClientId + uint32 connectionId, uint32 clientId, uint32 counterpartyClientId ); event ConnectionOpenTry( - string connectionId, - string clientId, - string counterpartyClientId, - string counterpartyConnectionId + uint32 connectionId, + uint32 clientId, + uint32 counterpartyClientId, + uint32 counterpartyConnectionId ); event ConnectionOpenAck( - string connectionId, - string clientId, - string counterpartyClientId, - string counterpartyConnectionId + uint32 connectionId, + uint32 clientId, + uint32 counterpartyClientId, + uint32 counterpartyConnectionId ); event ConnectionOpenConfirm( - string connectionId, - string clientId, - string counterpartyClientId, - string counterpartyConnectionId + uint32 connectionId, + uint32 clientId, + uint32 counterpartyClientId, + uint32 counterpartyConnectionId ); - error ErrConnectionAlreadyExists(); - error ErrValidateSelfClient(); - error ErrNoCounterpartyVersion(); - error ErrUnsupportedVersion(); - error ErrVersionMustBeUnset(); error ErrInvalidProof(); error ErrInvalidConnectionState(); - - // yes, these are all defined as strings in the ibc spec - string internal constant IBC_VERSION_IDENTIFIER = "1"; - string internal constant ORDER_ORDERED = "ORDER_ORDERED"; - string internal constant ORDER_UNORDERED = "ORDER_UNORDERED"; - - /** - * @dev defaultIBCVersion returns the latest supported version of IBC used in connection version negotiation - */ - function defaultIBCVersion() - internal - pure - returns (IbcCoreConnectionV1Version.Data memory) - { - IbcCoreConnectionV1Version.Data memory version = - IbcCoreConnectionV1Version.Data({ - identifier: IBC_VERSION_IDENTIFIER, - features: new string[](2) - }); - version.features[0] = ORDER_ORDERED; - version.features[1] = ORDER_UNORDERED; - return version; - } - - /** - * @dev setSupportedVersions sets the supported versions to a given array. - * - * NOTE: `dst` must be an empty array - */ - function setSupportedVersions( - IbcCoreConnectionV1Version.Data[] memory supportedVersions, - IbcCoreConnectionV1Version.Data[] storage dst - ) internal { - if (dst.length != 0) { - revert ErrVersionMustBeUnset(); - } - uint256 supportedVersionsLength = supportedVersions.length; - for (uint256 i; i < supportedVersionsLength; i++) { - dst.push(supportedVersions[i]); - } - } - - /** - * @dev isSupportedVersion returns true if the proposed version has a matching version - * identifier and its entire feature set is supported or the version identifier - * supports an empty feature set. - */ - function isSupportedVersion( - IbcCoreConnectionV1Version.Data[] memory supportedVersions, - IbcCoreConnectionV1Version.Data memory version - ) internal pure returns (bool) { - (IbcCoreConnectionV1Version.Data memory supportedVersion, bool found) = - findSupportedVersion(version, supportedVersions); - if (!found) { - return false; - } - return verifyProposedVersion(supportedVersion, version); - } - - function isSupported( - IbcCoreConnectionV1Version.Data[] storage supportedVersions, - string memory feature - ) internal view returns (bool) { - uint256 supportedVersionsLength = supportedVersions.length; - for (uint256 i; i < supportedVersionsLength; i++) { - if (verifySupportedFeature(supportedVersions[i], feature)) { - return true; - } - } - return false; - } - - /** - * @dev verifyProposedVersion verifies that the entire feature set in the - * proposed version is supported by this chain. If the feature set is - * empty it verifies that this is allowed for the specified version - * identifier. - */ - function verifyProposedVersion( - IbcCoreConnectionV1Version.Data memory supportedVersion, - IbcCoreConnectionV1Version.Data memory proposedVersion - ) internal pure returns (bool) { - if ( - keccak256(abi.encodePacked(proposedVersion.identifier)) - != keccak256(abi.encodePacked(supportedVersion.identifier)) - ) { - return false; - } - uint256 proposedVersionFeaturesLength = proposedVersion.features.length; - if (proposedVersionFeaturesLength == 0) { - return false; - } - for (uint256 i; i < proposedVersionFeaturesLength; i++) { - if ( - !contains(proposedVersion.features[i], supportedVersion.features) - ) { - return false; - } - } - return true; - } - - /** - * @dev findSupportedVersion returns the version with a matching version identifier - * if it exists. The returned boolean is true if the version is found and - * false otherwise. - */ - function findSupportedVersion( - IbcCoreConnectionV1Version.Data memory version, - IbcCoreConnectionV1Version.Data[] memory supportedVersions - ) - internal - pure - returns ( - IbcCoreConnectionV1Version.Data memory supportedVersion, - bool found - ) - { - uint256 supportedVersionsLength = supportedVersions.length; - for (uint256 i; i < supportedVersionsLength; i++) { - supportedVersion = supportedVersions[i]; - if ( - keccak256(abi.encodePacked(supportedVersion.identifier)) - == keccak256(abi.encodePacked(version.identifier)) - ) { - return (supportedVersion, true); - } - } - return (supportedVersion, false); - } - - function pickVersion( - IbcCoreConnectionV1Version.Data[] memory supportedVersions, - IbcCoreConnectionV1Version.Data[] memory counterpartyVersions - ) internal pure returns (IbcCoreConnectionV1Version.Data memory) { - uint256 supportedVersionsLength = supportedVersions.length; - for (uint256 i; i < supportedVersionsLength; i++) { - IbcCoreConnectionV1Version.Data memory supportedVersion = - supportedVersions[i]; - ( - IbcCoreConnectionV1Version.Data memory counterpartyVersion, - bool found - ) = findSupportedVersion(supportedVersion, counterpartyVersions); - if (!found) { - continue; - } - string[] memory featureSet = getFeatureSetIntersection( - supportedVersion.features, counterpartyVersion.features - ); - if (featureSet.length > 0) { - return IbcCoreConnectionV1Version.Data({ - identifier: supportedVersion.identifier, - features: featureSet - }); - } - } - revert ErrUnsupportedVersion(); - } - - /** - * @dev copyVersions copies `src` to `dst` - */ - function copyVersions( - IbcCoreConnectionV1Version.Data[] memory src, - IbcCoreConnectionV1Version.Data[] storage dst - ) internal { - uint256 srcLength = src.length; - uint256 dstLength = dst.length; - if (srcLength == dstLength) { - for (uint256 i; i < srcLength; i++) { - copyVersion(src[i], dst[i]); - } - } else if (srcLength > dstLength) { - for (uint256 i; i < dstLength; i++) { - copyVersion(src[i], dst[i]); - } - for (uint256 i = dstLength; i < srcLength; i++) { - dst.push(src[i]); - } - } else { - for (uint256 i; i < srcLength; i++) { - copyVersion(src[i], dst[i]); - } - for (uint256 i = srcLength; i < dstLength; i++) { - dst.pop(); - } - } - } - - /** - * @dev newVersions returns a new array with a given version - */ - function newVersions(IbcCoreConnectionV1Version.Data memory version) - internal - pure - returns (IbcCoreConnectionV1Version.Data[] memory ret) - { - ret = new IbcCoreConnectionV1Version.Data[](1); - ret[0] = version; - } - - /** - * @dev verifySupportedFeature takes in a version and feature string and returns - * true if the feature is supported by the version and false otherwise. - */ - function verifySupportedFeature( - IbcCoreConnectionV1Version.Data memory version, - string memory feature - ) internal pure returns (bool) { - bytes32 hashedFeature = keccak256(bytes(feature)); - uint256 versionFeaturesLength = version.features.length; - for (uint256 i; i < versionFeaturesLength; i++) { - if (keccak256(bytes(version.features[i])) == hashedFeature) { - return true; - } - } - return false; - } - - function getFeatureSetIntersection( - string[] memory sourceFeatureSet, - string[] memory counterpartyFeatureSet - ) private pure returns (string[] memory) { - uint256 sourceFeatureSetLength = sourceFeatureSet.length; - string[] memory featureSet = new string[](sourceFeatureSetLength); - uint256 featureSetLength; - for (uint256 i; i < sourceFeatureSetLength; i++) { - if (contains(sourceFeatureSet[i], counterpartyFeatureSet)) { - featureSet[featureSetLength] = sourceFeatureSet[i]; - featureSetLength++; - } - } - string[] memory ret = new string[](featureSetLength); - for (uint256 i; i < featureSetLength; i++) { - ret[i] = featureSet[i]; - } - return ret; - } - - function copyVersion( - IbcCoreConnectionV1Version.Data memory src, - IbcCoreConnectionV1Version.Data storage dst - ) private { - dst.identifier = src.identifier; - uint256 srcLength = src.features.length; - uint256 dstLength = dst.features.length; - - if (srcLength == dstLength) { - for (uint256 i; i < srcLength; i++) { - dst.features[i] = src.features[i]; - } - } else if (srcLength > dstLength) { - for (uint256 i; i < dstLength; i++) { - dst.features[i] = src.features[i]; - } - for (uint256 i = dstLength; i < srcLength; i++) { - dst.features.push(src.features[i]); - } - } else { - for (uint256 i; i < srcLength; i++) { - dst.features[i] = src.features[i]; - } - for (uint256 i = srcLength; i < dstLength; i++) { - dst.features.pop(); - } - } - } - - function contains( - string memory elem, - string[] memory set - ) private pure returns (bool) { - bytes32 hashedElem = keccak256(bytes(elem)); - uint256 setLength = set.length; - for (uint256 i; i < setLength; i++) { - if (keccak256(bytes(set[i])) == hashedElem) { - return true; - } - } - return false; - } } /** * @dev IBCConnection is a contract that implements [ICS-3](https://github.com/cosmos/ibc/tree/main/spec/core/ics-003-connection-semantics). */ -contract IBCConnection is IBCStore, IIBCConnectionHandshake { - using LibString for *; - - /* Handshake functions */ - +abstract contract IBCConnectionImpl is IBCStore, IIBCConnection { /** * @dev connectionOpenInit initialises a connection attempt on chain A. The generated connection identifier * is returned. @@ -337,46 +43,18 @@ contract IBCConnection is IBCStore, IIBCConnectionHandshake { function connectionOpenInit(IBCMsgs.MsgConnectionOpenInit calldata msg_) external override - returns (string memory) + returns (uint32) { - string memory connectionId = generateConnectionIdentifier(); - IbcCoreConnectionV1ConnectionEnd.Data storage connection = - connections[connectionId]; - if ( - connection.state - != IbcCoreConnectionV1GlobalEnums - .State - .STATE_UNINITIALIZED_UNSPECIFIED - ) { - revert IBCConnectionLib.ErrConnectionAlreadyExists(); - } - - connection.client_id = msg_.clientId; - - if (msg_.version.features.length > 0) { - if ( - !IBCConnectionLib.isSupportedVersion( - getCompatibleVersions(), msg_.version - ) - ) { - revert IBCConnectionLib.ErrUnsupportedVersion(); - } - connection.versions.push(msg_.version); - } else { - IBCConnectionLib.setSupportedVersions( - getCompatibleVersions(), connection.versions - ); - } - - connection.state = IbcCoreConnectionV1GlobalEnums.State.STATE_INIT; - connection.delay_period = msg_.delayPeriod; + uint32 connectionId = generateConnectionIdentifier(); + IBCConnection storage connection = connections[connectionId]; + connection.clientId = msg_.clientId; + connection.state = IBCConnectionState.Init; + connection.delayPeriod = msg_.delayPeriod; connection.counterparty = msg_.counterparty; - updateConnectionCommitment(connectionId); - + commitConnection(connectionId, connection); emit IBCConnectionLib.ConnectionOpenInit( - connectionId, msg_.clientId, msg_.counterparty.client_id + connectionId, msg_.clientId, msg_.counterparty.clientId ); - return connectionId; } @@ -387,85 +65,42 @@ contract IBCConnection is IBCStore, IIBCConnectionHandshake { function connectionOpenTry(IBCMsgs.MsgConnectionOpenTry calldata msg_) external override - returns (string memory) + returns (uint32) { - if (!validateSelfClient(msg_.clientStateBytes)) { - revert IBCConnectionLib.ErrValidateSelfClient(); - } - if (msg_.counterpartyVersions.length == 0) { - revert IBCConnectionLib.ErrNoCounterpartyVersion(); - } - - string memory connectionId = generateConnectionIdentifier(); - IbcCoreConnectionV1ConnectionEnd.Data storage connection = - connections[connectionId]; - - if ( - connection.state - != IbcCoreConnectionV1GlobalEnums - .State - .STATE_UNINITIALIZED_UNSPECIFIED - ) { - revert IBCConnectionLib.ErrConnectionAlreadyExists(); - } - - connection.client_id = msg_.clientId; - connection.versions.push( - IBCConnectionLib.pickVersion( - getCompatibleVersions(), msg_.counterpartyVersions - ) - ); - connection.state = IbcCoreConnectionV1GlobalEnums.State.STATE_TRYOPEN; - connection.delay_period = msg_.delayPeriod; + uint32 connectionId = generateConnectionIdentifier(); + IBCConnection storage connection = connections[connectionId]; + connection.clientId = msg_.clientId; + connection.state = IBCConnectionState.TryOpen; + connection.delayPeriod = msg_.delayPeriod; connection.counterparty = msg_.counterparty; - - IbcCoreConnectionV1ConnectionEnd.Data memory expectedConnection = - IbcCoreConnectionV1ConnectionEnd.Data({ - client_id: msg_.counterparty.client_id, - versions: msg_.counterpartyVersions, - state: IbcCoreConnectionV1GlobalEnums.State.STATE_INIT, - delay_period: msg_.delayPeriod, - counterparty: IbcCoreConnectionV1Counterparty.Data({ - client_id: msg_.clientId, - connection_id: "", - prefix: IbcCoreCommitmentV1MerklePrefix.Data({ - key_prefix: bytes(COMMITMENT_PREFIX) - }) + IBCConnection memory expectedConnection = IBCConnection({ + clientId: msg_.counterparty.clientId, + state: IBCConnectionState.Init, + delayPeriod: msg_.delayPeriod, + counterparty: IBCConnectionCounterparty({ + clientId: msg_.clientId, + connectionId: 0, + merklePrefix: COMMITMENT_PREFIX }) }); - if ( !verifyConnectionState( connection, msg_.proofHeight, msg_.proofInit, - msg_.counterparty.connection_id, + msg_.counterparty.connectionId, expectedConnection ) ) { revert IBCConnectionLib.ErrInvalidProof(); } - if ( - !verifyClientState( - connection, - msg_.proofHeight, - IBCCommitment.clientStatePath(connection.counterparty.client_id), - msg_.proofClient, - msg_.clientStateBytes - ) - ) { - revert IBCConnectionLib.ErrInvalidProof(); - } - - updateConnectionCommitment(connectionId); - + commitConnection(connectionId, connection); emit IBCConnectionLib.ConnectionOpenTry( connectionId, msg_.clientId, - msg_.counterparty.client_id, - msg_.counterparty.connection_id + msg_.counterparty.clientId, + msg_.counterparty.connectionId ); - return connectionId; } @@ -477,76 +112,41 @@ contract IBCConnection is IBCStore, IIBCConnectionHandshake { external override { - IbcCoreConnectionV1ConnectionEnd.Data storage connection = - connections[msg_.connectionId]; - if (connection.state != IbcCoreConnectionV1GlobalEnums.State.STATE_INIT) - { + IBCConnection storage connection = connections[msg_.connectionId]; + if (connection.state != IBCConnectionState.Init) { revert IBCConnectionLib.ErrInvalidConnectionState(); } - if ( - !IBCConnectionLib.isSupportedVersion( - connection.versions, msg_.version - ) - ) { - revert IBCConnectionLib.ErrUnsupportedVersion(); - } - if (!validateSelfClient(msg_.clientStateBytes)) { - revert IBCConnectionLib.ErrValidateSelfClient(); - } - - IbcCoreConnectionV1Counterparty.Data memory expectedCounterparty = - IbcCoreConnectionV1Counterparty.Data({ - client_id: connection.client_id, - connection_id: msg_.connectionId, - prefix: IbcCoreCommitmentV1MerklePrefix.Data({ - key_prefix: bytes(COMMITMENT_PREFIX) - }) + IBCConnectionCounterparty memory expectedCounterparty = + IBCConnectionCounterparty({ + clientId: connection.clientId, + connectionId: msg_.connectionId, + merklePrefix: COMMITMENT_PREFIX }); - - IbcCoreConnectionV1ConnectionEnd.Data memory expectedConnection = - IbcCoreConnectionV1ConnectionEnd.Data({ - client_id: connection.counterparty.client_id, - versions: IBCConnectionLib.newVersions(msg_.version), - state: IbcCoreConnectionV1GlobalEnums.State.STATE_TRYOPEN, - delay_period: connection.delay_period, + IBCConnection memory expectedConnection = IBCConnection({ + clientId: connection.counterparty.clientId, + state: IBCConnectionState.TryOpen, + delayPeriod: connection.delayPeriod, counterparty: expectedCounterparty }); - if ( !verifyConnectionState( connection, msg_.proofHeight, msg_.proofTry, - msg_.counterpartyConnectionID, + msg_.counterpartyConnectionId, expectedConnection ) ) { revert IBCConnectionLib.ErrInvalidProof(); } - if ( - !verifyClientState( - connection, - msg_.proofHeight, - IBCCommitment.clientStatePath(connection.counterparty.client_id), - msg_.proofClient, - msg_.clientStateBytes - ) - ) { - revert IBCConnectionLib.ErrInvalidProof(); - } - - connection.state = IbcCoreConnectionV1GlobalEnums.State.STATE_OPEN; - IBCConnectionLib.copyVersions( - expectedConnection.versions, connection.versions - ); - connection.counterparty.connection_id = msg_.counterpartyConnectionID; - updateConnectionCommitment(msg_.connectionId); - + connection.state = IBCConnectionState.Open; + connection.counterparty.connectionId = msg_.counterpartyConnectionId; + commitConnection(msg_.connectionId, connection); emit IBCConnectionLib.ConnectionOpenAck( msg_.connectionId, - connection.client_id, - connection.counterparty.client_id, - connection.counterparty.connection_id + connection.clientId, + connection.counterparty.clientId, + connection.counterparty.connectionId ); } @@ -557,145 +157,91 @@ contract IBCConnection is IBCStore, IIBCConnectionHandshake { function connectionOpenConfirm( IBCMsgs.MsgConnectionOpenConfirm calldata msg_ ) external override { - IbcCoreConnectionV1ConnectionEnd.Data storage connection = - connections[msg_.connectionId]; - if ( - connection.state - != IbcCoreConnectionV1GlobalEnums.State.STATE_TRYOPEN - ) { + IBCConnection storage connection = connections[msg_.connectionId]; + if (connection.state != IBCConnectionState.TryOpen) { revert IBCConnectionLib.ErrInvalidConnectionState(); } - - IbcCoreConnectionV1Counterparty.Data memory expectedCounterparty = - IbcCoreConnectionV1Counterparty.Data({ - client_id: connection.client_id, - connection_id: msg_.connectionId, - prefix: IbcCoreCommitmentV1MerklePrefix.Data({ - key_prefix: bytes(COMMITMENT_PREFIX) - }) + IBCConnectionCounterparty memory expectedCounterparty = + IBCConnectionCounterparty({ + clientId: connection.clientId, + connectionId: msg_.connectionId, + merklePrefix: COMMITMENT_PREFIX }); - - IbcCoreConnectionV1ConnectionEnd.Data memory expectedConnection = - IbcCoreConnectionV1ConnectionEnd.Data({ - client_id: connection.counterparty.client_id, - versions: connection.versions, - state: IbcCoreConnectionV1GlobalEnums.State.STATE_OPEN, - delay_period: connection.delay_period, + IBCConnection memory expectedConnection = IBCConnection({ + clientId: connection.counterparty.clientId, + state: IBCConnectionState.Open, + delayPeriod: connection.delayPeriod, counterparty: expectedCounterparty }); - if ( !verifyConnectionState( connection, msg_.proofHeight, msg_.proofAck, - connection.counterparty.connection_id, + connection.counterparty.connectionId, expectedConnection ) ) { revert IBCConnectionLib.ErrInvalidProof(); } - - connection.state = IbcCoreConnectionV1GlobalEnums.State.STATE_OPEN; - updateConnectionCommitment(msg_.connectionId); - + connection.state = IBCConnectionState.Open; + commitConnection(msg_.connectionId, connection); emit IBCConnectionLib.ConnectionOpenConfirm( msg_.connectionId, - connection.client_id, - connection.counterparty.client_id, - connection.counterparty.connection_id + connection.clientId, + connection.counterparty.clientId, + connection.counterparty.connectionId ); } - function updateConnectionCommitment(string memory connectionId) private { - commitments[IBCCommitment.connectionCommitmentKey(connectionId)] = - keccak256( - IbcCoreConnectionV1ConnectionEnd.encode(connections[connectionId]) - ); + function encodeConnection(IBCConnection memory connection) + internal + pure + returns (bytes32) + { + return keccak256(abi.encode(connection)); } - /* Verification functions */ + function encodeConnectionStorage(IBCConnection storage connection) + internal + pure + returns (bytes32) + { + return keccak256(abi.encode(connection)); + } - function verifyClientState( - IbcCoreConnectionV1ConnectionEnd.Data storage connection, - IbcCoreClientV1Height.Data memory height, - bytes memory path, - bytes memory proof, - bytes memory clientStateBytes - ) private returns (bool) { - return getClient(connection.client_id).verifyMembership( - connection.client_id, - height, - 0, - 0, - proof, - connection.counterparty.prefix.key_prefix, - path, - clientStateBytes - ); + function commitConnection( + uint32 connectionId, + IBCConnection storage connection + ) internal { + commitments[IBCCommitment.connectionCommitmentKey(connectionId)] = + encodeConnectionStorage(connection); } function verifyConnectionState( - IbcCoreConnectionV1ConnectionEnd.Data storage connection, - IbcCoreClientV1Height.Data memory height, - bytes memory proof, - string memory connectionId, - IbcCoreConnectionV1ConnectionEnd.Data memory counterpartyConnection - ) private returns (bool) { - return getClient(connection.client_id).verifyMembership( - connection.client_id, + IBCConnection storage connection, + IBCHeight calldata height, + bytes calldata proof, + uint32 connectionId, + IBCConnection memory counterpartyConnection + ) internal returns (bool) { + return getClientInternal(connection.clientId).verifyMembership( + connection.clientId, height, 0, 0, proof, - connection.counterparty.prefix.key_prefix, + abi.encodePacked(connection.counterparty.merklePrefix), IBCCommitment.connectionPath(connectionId), - IbcCoreConnectionV1ConnectionEnd.encode(counterpartyConnection) + abi.encodePacked(encodeConnection(counterpartyConnection)) ); } - /* Internal functions */ - - function generateConnectionIdentifier() private returns (string memory) { - uint256 nextConnectionSequence = - uint256(commitments[nextConnectionSequencePath]); - - string memory identifier = string( - abi.encodePacked( - "connection-", Strings.toString(nextConnectionSequence) - ) - ); + function generateConnectionIdentifier() internal returns (uint32) { + uint32 nextConnectionSequence = + uint32(uint256(commitments[nextConnectionSequencePath])); commitments[nextConnectionSequencePath] = - bytes32(nextConnectionSequence + 1); - return identifier; - } - - /** - * @dev validateSelfClient validates the client parameters for a client of the host chain. - * - * NOTE: Developers can override this function to support an arbitrary EVM chain. - */ - function validateSelfClient(bytes memory) - internal - view - virtual - returns (bool) - { - return true; - } - - /** - * @dev getCompatibleVersions returns the supported versions of the host chain. - */ - function getCompatibleVersions() - public - pure - virtual - returns (IbcCoreConnectionV1Version.Data[] memory) - { - IbcCoreConnectionV1Version.Data[] memory versions = - new IbcCoreConnectionV1Version.Data[](1); - versions[0] = IBCConnectionLib.defaultIBCVersion(); - return versions; + bytes32(uint256(nextConnectionSequence + 1)); + return nextConnectionSequence; } } diff --git a/evm/contracts/core/03-connection/IIBCConnection.sol b/evm/contracts/core/03-connection/IIBCConnection.sol index ab8094ecdc..5614cc352c 100644 --- a/evm/contracts/core/03-connection/IIBCConnection.sol +++ b/evm/contracts/core/03-connection/IIBCConnection.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.23; import "../25-handler/IBCMsgs.sol"; -interface IIBCConnectionHandshake { +interface IIBCConnection { /* Handshake functions */ /** @@ -11,7 +11,7 @@ interface IIBCConnectionHandshake { */ function connectionOpenInit(IBCMsgs.MsgConnectionOpenInit calldata msg_) external - returns (string memory); + returns (uint32); /** * @dev connectionOpenTry relays notice of a connection attempt on chain A to chain B (this @@ -19,7 +19,7 @@ interface IIBCConnectionHandshake { */ function connectionOpenTry(IBCMsgs.MsgConnectionOpenTry calldata msg_) external - returns (string memory); + returns (uint32); /** * @dev connectionOpenAck relays acceptance of a connection open attempt from chain B back diff --git a/evm/contracts/core/04-channel/IBCChannel.sol b/evm/contracts/core/04-channel/IBCChannel.sol new file mode 100644 index 0000000000..fc57c47686 --- /dev/null +++ b/evm/contracts/core/04-channel/IBCChannel.sol @@ -0,0 +1,422 @@ +pragma solidity ^0.8.23; + +import "../24-host/IBCStore.sol"; +import "../25-handler/IBCMsgs.sol"; +import "../02-client/IBCHeight.sol"; +import "../24-host/IBCCommitment.sol"; +import "../04-channel/IIBCChannel.sol"; +import "../05-port/IIBCModule.sol"; + +library IBCChannelLib { + event ChannelOpenInit( + address portId, + uint32 channelId, + bytes32 counterpartyPortId, + uint32 connectionId, + bytes32 version + ); + event ChannelOpenTry( + address portId, + uint32 channelId, + bytes32 counterpartyPortId, + uint32 counterpartyChannelId, + uint32 connectionId, + bytes32 version + ); + event ChannelOpenAck( + address portId, + uint32 channelId, + bytes32 counterpartyPortId, + uint32 counterpartyChannelId, + uint32 connectionId + ); + event ChannelOpenConfirm( + address portId, + uint32 channelId, + bytes32 counterpartyPortId, + uint32 counterpartyChannelId, + uint32 connectionId + ); + event ChannelCloseInit(address portId, uint32 channelId); + event ChannelCloseConfirm(address portId, uint32 channelId); + + error ErrPortIdMustBeLowercase(); + error ErrConnNotSingleHop(); + error ErrConnNotSingleVersion(); + error ErrInvalidConnectionState(); + error ErrUnsupportedFeature(); + error ErrInvalidChannelState(); + error ErrCounterpartyChannelNotEmpty(); + error ErrInvalidProof(); + error ErrInvalidChannelOrdering(); +} + +/** + * @dev IBCChannelHandshake is a contract that implements [ICS-4](https://github.com/cosmos/ibc/tree/main/spec/core/ics-004-channel-and-packet-semantics). + */ +abstract contract IBCChannelImpl is IBCStore, IIBCChannel { + using IBCHeightLib for IBCHeight; + + /** + * @dev channelOpenInit is called by a module to initiate a channel opening handshake with a module on another chain. + */ + function channelOpenInit(IBCMsgs.MsgChannelOpenInit calldata msg_) + external + override + returns (uint32) + { + if (msg_.channel.state != IBCChannelState.Init) { + revert IBCChannelLib.ErrInvalidChannelState(); + } + if ( + msg_.channel.ordering != IBCChannelOrder.Unordered + && msg_.channel.ordering != IBCChannelOrder.Ordered + ) { + revert IBCChannelLib.ErrInvalidChannelOrdering(); + } + bytes32 normalizedPortId = keccak256(abi.encodePacked(msg_.portId)); + uint32 channelId = generateChannelIdentifier(); + channels[channelId] = msg_.channel; + initializeChannelSequences(normalizedPortId, channelId); + commitChannelCalldata(normalizedPortId, channelId, msg_.channel); + claimChannel(msg_.portId, channelId); + IIBCModule(msg_.portId).onChanOpenInit( + msg_.channel.ordering, + msg_.channel.connectionId, + channelId, + msg_.channel.counterparty, + msg_.channel.version, + msg_.relayer + ); + emit IBCChannelLib.ChannelOpenInit( + msg_.portId, + channelId, + msg_.channel.counterparty.portId, + msg_.channel.connectionId, + msg_.channel.version + ); + return channelId; + } + + /** + * @dev channelOpenTry is called by a module to accept the first step of a channel opening handshake initiated by a module on another chain. + */ + function channelOpenTry(IBCMsgs.MsgChannelOpenTry calldata msg_) + external + override + returns (uint32) + { + if ( + msg_.channel.ordering != IBCChannelOrder.Unordered + && msg_.channel.ordering != IBCChannelOrder.Ordered + ) { + revert IBCChannelLib.ErrInvalidChannelOrdering(); + } + if (msg_.channel.state != IBCChannelState.TryOpen) { + revert IBCChannelLib.ErrInvalidChannelState(); + } + IBCConnection storage connection = + ensureConnectionState(msg_.channel.connectionId); + bytes32 normalizedPortId = keccak256(abi.encodePacked(msg_.portId)); + IBCChannelCounterparty memory expectedCounterparty = + IBCChannelCounterparty({portId: normalizedPortId, channelId: 0}); + IBCChannel memory expectedChannel = IBCChannel({ + state: IBCChannelState.Init, + ordering: msg_.channel.ordering, + counterparty: expectedCounterparty, + connectionId: getCounterpartyConnection(msg_.channel.connectionId), + version: msg_.counterpartyVersion + }); + if ( + !verifyChannelState( + connection, + msg_.proofHeight, + msg_.proofInit, + msg_.channel.counterparty.portId, + msg_.channel.counterparty.channelId, + expectedChannel + ) + ) { + revert IBCChannelLib.ErrInvalidProof(); + } + uint32 channelId = generateChannelIdentifier(); + channels[channelId] = msg_.channel; + initializeChannelSequences(normalizedPortId, channelId); + commitChannelCalldata(normalizedPortId, channelId, msg_.channel); + claimChannel(msg_.portId, channelId); + IIBCModule(msg_.portId).onChanOpenTry( + msg_.channel.ordering, + msg_.channel.connectionId, + channelId, + msg_.channel.counterparty, + msg_.channel.version, + msg_.counterpartyVersion, + msg_.relayer + ); + emit IBCChannelLib.ChannelOpenTry( + msg_.portId, + channelId, + msg_.channel.counterparty.portId, + msg_.channel.counterparty.channelId, + msg_.channel.connectionId, + msg_.counterpartyVersion + ); + return channelId; + } + + /** + * @dev channelOpenAck is called by the handshake-originating module to acknowledge the acceptance of the initial request by the counterparty module on the other chain. + */ + function channelOpenAck(IBCMsgs.MsgChannelOpenAck calldata msg_) + external + override + { + IBCChannel storage channel = channels[msg_.channelId]; + if (channel.state != IBCChannelState.Init) { + revert IBCChannelLib.ErrInvalidChannelState(); + } + IBCConnection storage connection = + ensureConnectionState(channel.connectionId); + bytes32 normalizedPortId = keccak256(abi.encodePacked(msg_.portId)); + IBCChannelCounterparty memory expectedCounterparty = + IBCChannelCounterparty({ + portId: normalizedPortId, + channelId: msg_.channelId + }); + IBCChannel memory expectedChannel = IBCChannel({ + state: IBCChannelState.TryOpen, + ordering: channel.ordering, + counterparty: expectedCounterparty, + connectionId: getCounterpartyConnection(channel.connectionId), + version: msg_.counterpartyVersion + }); + if ( + !verifyChannelState( + connection, + msg_.proofHeight, + msg_.proofTry, + channel.counterparty.portId, + msg_.counterpartyChannelId, + expectedChannel + ) + ) { + revert IBCChannelLib.ErrInvalidProof(); + } + channel.state = IBCChannelState.Open; + channel.version = msg_.counterpartyVersion; + channel.counterparty.channelId = msg_.counterpartyChannelId; + commitChannel(normalizedPortId, msg_.channelId, channel); + IIBCModule(msg_.portId).onChanOpenAck( + msg_.channelId, + msg_.counterpartyChannelId, + msg_.counterpartyVersion, + msg_.relayer + ); + emit IBCChannelLib.ChannelOpenAck( + msg_.portId, + msg_.channelId, + channel.counterparty.portId, + msg_.counterpartyChannelId, + channel.connectionId + ); + } + + /** + * @dev channelOpenConfirm is called by the counterparty module to close their end of the channel, since the other end has been closed. + */ + function channelOpenConfirm(IBCMsgs.MsgChannelOpenConfirm calldata msg_) + external + override + { + IBCChannel storage channel = channels[msg_.channelId]; + if (channel.state != IBCChannelState.TryOpen) { + revert IBCChannelLib.ErrInvalidChannelState(); + } + IBCConnection storage connection = + ensureConnectionState(channel.connectionId); + bytes32 normalizedPortId = keccak256(abi.encodePacked(msg_.portId)); + IBCChannelCounterparty memory expectedCounterparty = + IBCChannelCounterparty({ + portId: normalizedPortId, + channelId: msg_.channelId + }); + IBCChannel memory expectedChannel = IBCChannel({ + state: IBCChannelState.Open, + ordering: channel.ordering, + counterparty: expectedCounterparty, + connectionId: getCounterpartyConnection(channel.connectionId), + version: channel.version + }); + if ( + !verifyChannelState( + connection, + msg_.proofHeight, + msg_.proofAck, + channel.counterparty.portId, + channel.counterparty.channelId, + expectedChannel + ) + ) { + revert IBCChannelLib.ErrInvalidProof(); + } + channel.state = IBCChannelState.Open; + commitChannel(normalizedPortId, msg_.channelId, channel); + IIBCModule(msg_.portId).onChanOpenConfirm(msg_.channelId, msg_.relayer); + emit IBCChannelLib.ChannelOpenConfirm( + msg_.portId, + msg_.channelId, + channel.counterparty.portId, + channel.counterparty.channelId, + channel.connectionId + ); + } + + /** + * @dev channelCloseInit is called by either module to close their end of the channel. Once closed, channels cannot be reopened. + */ + function channelCloseInit(IBCMsgs.MsgChannelCloseInit calldata msg_) + external + override + { + IBCChannel storage channel = channels[msg_.channelId]; + if (channel.state != IBCChannelState.Open) { + revert IBCChannelLib.ErrInvalidChannelState(); + } + ensureConnectionState(channel.connectionId); + channel.state = IBCChannelState.Closed; + bytes32 normalizedPortId = keccak256(abi.encodePacked(msg_.portId)); + commitChannel(normalizedPortId, msg_.channelId, channel); + IIBCModule(msg_.portId).onChanCloseInit(msg_.channelId, msg_.relayer); + emit IBCChannelLib.ChannelCloseInit(msg_.portId, msg_.channelId); + } + + /** + * @dev channelCloseConfirm is called by the counterparty module to close their end of the + * channel, since the other end has been closed. + */ + function channelCloseConfirm(IBCMsgs.MsgChannelCloseConfirm calldata msg_) + external + override + { + IBCChannel storage channel = channels[msg_.channelId]; + if (channel.state != IBCChannelState.Open) { + revert IBCChannelLib.ErrInvalidChannelState(); + } + IBCConnection storage connection = + ensureConnectionState(channel.connectionId); + bytes32 normalizedPortId = keccak256(abi.encodePacked(msg_.portId)); + IBCChannelCounterparty memory expectedCounterparty = + IBCChannelCounterparty({ + portId: normalizedPortId, + channelId: msg_.channelId + }); + IBCChannel memory expectedChannel = IBCChannel({ + state: IBCChannelState.Closed, + ordering: channel.ordering, + counterparty: expectedCounterparty, + connectionId: getCounterpartyConnection(channel.connectionId), + version: channel.version + }); + if ( + !verifyChannelState( + connection, + msg_.proofHeight, + msg_.proofInit, + channel.counterparty.portId, + channel.counterparty.channelId, + expectedChannel + ) + ) { + revert IBCChannelLib.ErrInvalidProof(); + } + channel.state = IBCChannelState.Closed; + commitChannel(normalizedPortId, msg_.channelId, channel); + IIBCModule(msg_.portId).onChanCloseConfirm(msg_.channelId, msg_.relayer); + emit IBCChannelLib.ChannelCloseConfirm(msg_.portId, msg_.channelId); + } + + function encodeChannel(IBCChannel memory channel) + internal + pure + returns (bytes32) + { + return keccak256(abi.encode(channel)); + } + + function commitChannel( + bytes32 portId, + uint32 channelId, + IBCChannel storage channel + ) internal { + commitments[IBCCommitment.channelCommitmentKey(portId, channelId)] = + encodeChannel(channel); + } + + function encodeChannelCalldata(IBCChannel calldata channel) + internal + pure + returns (bytes32) + { + return keccak256(abi.encode(channel)); + } + + function commitChannelCalldata( + bytes32 portId, + uint32 channelId, + IBCChannel calldata channel + ) internal { + commitments[IBCCommitment.channelCommitmentKey(portId, channelId)] = + encodeChannelCalldata(channel); + } + + function verifyChannelState( + IBCConnection storage connection, + IBCHeight calldata height, + bytes calldata proof, + bytes32 portId, + uint32 channelId, + IBCChannel memory channel + ) internal returns (bool) { + return getClientInternal(connection.clientId).verifyMembership( + connection.clientId, + height, + 0, + 0, + proof, + abi.encodePacked(connection.counterparty.merklePrefix), + IBCCommitment.channelPath(portId, channelId), + abi.encodePacked(encodeChannel(channel)) + ); + } + + function getCounterpartyConnection(uint32 connectionId) + internal + view + returns (uint32) + { + return connections[connectionId].counterparty.connectionId; + } + + function generateChannelIdentifier() internal returns (uint32) { + uint32 nextChannelSequence = + uint32(uint256(commitments[nextChannelSequencePath])); + commitments[nextChannelSequencePath] = + bytes32(uint256(nextChannelSequence + 1)); + return nextChannelSequence; + } + + function initializeChannelSequences( + bytes32 portId, + uint32 channelId + ) internal { + commitments[IBCCommitment.nextSequenceSendCommitmentKey( + portId, channelId + )] = bytes32(uint256(1)); + commitments[IBCCommitment.nextSequenceRecvCommitmentKey( + portId, channelId + )] = bytes32(uint256(1)); + commitments[IBCCommitment.nextSequenceAckCommitmentKey( + portId, channelId + )] = bytes32(uint256(1)); + } +} diff --git a/evm/contracts/core/04-channel/IBCChannelHandshake.sol b/evm/contracts/core/04-channel/IBCChannelHandshake.sol deleted file mode 100644 index 6c29e2ed0e..0000000000 --- a/evm/contracts/core/04-channel/IBCChannelHandshake.sol +++ /dev/null @@ -1,551 +0,0 @@ -pragma solidity ^0.8.23; - -import "@openzeppelin/utils/Strings.sol"; -import "solady/utils/LibString.sol"; - -import "../../proto/ibc/core/channel/v1/channel.sol"; -import "../25-handler/IBCMsgs.sol"; -import "../02-client/IBCHeight.sol"; -import "../24-host/IBCCommitment.sol"; -import "../04-channel/IIBCChannel.sol"; -import "../05-port/ModuleManager.sol"; -import "../05-port/IIBCModule.sol"; - -library IBCChannelLib { - event ChannelOpenInit( - string portId, - string channelId, - string counterpartyPortId, - string connectionId, - string version - ); - event ChannelOpenTry( - string portId, - string channelId, - string counterpartyPortId, - string counterpartyChannelId, - string connectionId, - string version - ); - event ChannelOpenAck( - string portId, - string channelId, - string counterpartyPortId, - string counterpartyChannelId, - string connectionId - ); - event ChannelOpenConfirm( - string portId, - string channelId, - string counterpartyPortId, - string counterpartyChannelId, - string connectionId - ); - event ChannelCloseInit(string channelId, string portId); - event ChannelCloseConfirm(string channelId, string portId); - - error ErrPortIdMustBeLowercase(); - error ErrConnNotSingleHop(); - error ErrConnNotSingleVersion(); - error ErrInvalidConnectionState(); - error ErrUnsupportedFeature(); - error ErrInvalidChannelState(); - error ErrCounterpartyChannelNotEmpty(); - error ErrInvalidProof(); - - string public constant ORDER_ORDERED = "ORDER_ORDERED"; - string public constant ORDER_UNORDERED = "ORDER_UNORDERED"; - string public constant ORDER_INVALID = "_ORDER_INVALID_"; - - function verifySupportedFeature( - IbcCoreConnectionV1Version.Data memory version, - string memory feature - ) internal pure returns (bool) { - bytes32 h = keccak256(bytes(feature)); - for (uint256 i; i < version.features.length; i++) { - if (keccak256(bytes(version.features[i])) == h) { - return true; - } - } - return false; - } - - function toString(IbcCoreChannelV1GlobalEnums.Order ordering) - internal - pure - returns (string memory) - { - if (ordering == IbcCoreChannelV1GlobalEnums.Order.ORDER_UNORDERED) { - return ORDER_UNORDERED; - } else if (ordering == IbcCoreChannelV1GlobalEnums.Order.ORDER_ORDERED) - { - return ORDER_ORDERED; - } else { - return ORDER_INVALID; - } - } -} - -/** - * @dev IBCChannelHandshake is a contract that implements [ICS-4](https://github.com/cosmos/ibc/tree/main/spec/core/ics-004-channel-and-packet-semantics). - */ -contract IBCChannelHandshake is ModuleManager, IIBCChannelHandshake { - using IBCHeight for IbcCoreClientV1Height.Data; - using LibString for *; - - /* Handshake functions */ - - /** - * @dev channelOpenInit is called by a module to initiate a channel opening handshake with a module on another chain. - */ - function channelOpenInit(IBCMsgs.MsgChannelOpenInit calldata msg_) - external - override - returns (string memory) - { - if (!msg_.portId.lower().eq(msg_.portId)) { - revert IBCChannelLib.ErrPortIdMustBeLowercase(); - } - (string memory connectionId,) = ensureConnectionFeature( - msg_.channel.connection_hops, msg_.channel.ordering - ); - if (msg_.channel.state != IbcCoreChannelV1GlobalEnums.State.STATE_INIT) - { - revert IBCChannelLib.ErrInvalidChannelState(); - } - if (bytes(msg_.channel.counterparty.channel_id).length != 0) { - revert IBCChannelLib.ErrCounterpartyChannelNotEmpty(); - } - - string memory channelId = generateChannelIdentifier(); - channels[msg_.portId][channelId] = msg_.channel; - - commitments[IBCCommitment.nextSequenceSendCommitmentKey( - msg_.portId, channelId - )] = bytes32(uint256(1)); - commitments[IBCCommitment.nextSequenceRecvCommitmentKey( - msg_.portId, channelId - )] = bytes32(uint256(1)); - - commitments[IBCCommitment.nextSequenceAckCommitmentKey( - msg_.portId, channelId - )] = bytes32(uint256(1)); - - updateChannelCommitment(msg_.portId, channelId); - - IIBCModule module = lookupModuleByPort(msg_.portId); - - claimCapability( - channelCapabilityPath(msg_.portId, channelId), address(module) - ); - - module.onChanOpenInit( - msg_.channel.ordering, - msg_.channel.connection_hops, - msg_.portId, - channelId, - msg_.channel.counterparty, - msg_.channel.version, - msg_.relayer - ); - - emit IBCChannelLib.ChannelOpenInit( - msg_.portId, - channelId, - msg_.channel.counterparty.port_id, - connectionId, - msg_.channel.version - ); - - return channelId; - } - - /** - * @dev channelOpenTry is called by a module to accept the first step of a channel opening handshake initiated by a module on another chain. - */ - function channelOpenTry(IBCMsgs.MsgChannelOpenTry calldata msg_) - external - override - returns (string memory) - { - if (!msg_.portId.lower().eq(msg_.portId)) { - revert IBCChannelLib.ErrPortIdMustBeLowercase(); - } - ( - string memory connectionId, - IbcCoreConnectionV1ConnectionEnd.Data memory connection - ) = ensureConnectionFeature( - msg_.channel.connection_hops, msg_.channel.ordering - ); - if ( - msg_.channel.state - != IbcCoreChannelV1GlobalEnums.State.STATE_TRYOPEN - ) { - revert IBCChannelLib.ErrInvalidChannelState(); - } - - IbcCoreChannelV1Counterparty.Data memory expectedCounterparty = - IbcCoreChannelV1Counterparty.Data({port_id: msg_.portId, channel_id: ""}); - IbcCoreChannelV1Channel.Data memory expectedChannel = - IbcCoreChannelV1Channel.Data({ - state: IbcCoreChannelV1GlobalEnums.State.STATE_INIT, - ordering: msg_.channel.ordering, - counterparty: expectedCounterparty, - connection_hops: getCounterpartyHops(msg_.channel.connection_hops[0]), - version: msg_.counterpartyVersion - }); - - if ( - !verifyChannelState( - connection, - msg_.proofHeight, - msg_.proofInit, - msg_.channel.counterparty.port_id, - msg_.channel.counterparty.channel_id, - IbcCoreChannelV1Channel.encode(expectedChannel) - ) - ) { - revert IBCChannelLib.ErrInvalidProof(); - } - - string memory channelId = generateChannelIdentifier(); - - emit IBCChannelLib.ChannelOpenTry( - msg_.portId, - channelId, - msg_.channel.counterparty.port_id, - msg_.channel.counterparty.channel_id, - connectionId, - msg_.counterpartyVersion - ); - - channels[msg_.portId][channelId] = msg_.channel; - commitments[IBCCommitment.nextSequenceSendCommitmentKey( - msg_.portId, channelId - )] = bytes32(uint256(1)); - commitments[IBCCommitment.nextSequenceRecvCommitmentKey( - msg_.portId, channelId - )] = bytes32(uint256(1)); - commitments[IBCCommitment.nextSequenceAckCommitmentKey( - msg_.portId, channelId - )] = bytes32(uint256(1)); - updateChannelCommitment(msg_.portId, channelId); - - IIBCModule module = lookupModuleByPort(msg_.portId); - - claimCapability( - channelCapabilityPath(msg_.portId, channelId), address(module) - ); - - module.onChanOpenTry( - msg_.channel.ordering, - msg_.channel.connection_hops, - msg_.portId, - channelId, - msg_.channel.counterparty, - msg_.channel.version, - msg_.counterpartyVersion, - msg_.relayer - ); - - return channelId; - } - - /** - * @dev channelOpenAck is called by the handshake-originating module to acknowledge the acceptance of the initial request by the counterparty module on the other chain. - */ - function channelOpenAck(IBCMsgs.MsgChannelOpenAck calldata msg_) - external - override - { - IbcCoreChannelV1Channel.Data storage channel = - channels[msg_.portId][msg_.channelId]; - if (channel.state != IbcCoreChannelV1GlobalEnums.State.STATE_INIT) { - revert IBCChannelLib.ErrInvalidChannelState(); - } - - emit IBCChannelLib.ChannelOpenAck( - msg_.portId, - msg_.channelId, - channel.counterparty.port_id, - // haven't been saved yet, but we have to yield the even early to avoid overflowing the stack - msg_.counterpartyChannelId, - channel.connection_hops[0] - ); - - IbcCoreConnectionV1ConnectionEnd.Data memory connection = - ensureConnectionState(channel.connection_hops[0]); - - IbcCoreChannelV1Counterparty.Data memory expectedCounterparty = - IbcCoreChannelV1Counterparty.Data({ - port_id: msg_.portId, - channel_id: msg_.channelId - }); - IbcCoreChannelV1Channel.Data memory expectedChannel = - IbcCoreChannelV1Channel.Data({ - state: IbcCoreChannelV1GlobalEnums.State.STATE_TRYOPEN, - ordering: channel.ordering, - counterparty: expectedCounterparty, - connection_hops: getCounterpartyHops(channel.connection_hops[0]), - version: msg_.counterpartyVersion - }); - - if ( - !verifyChannelState( - connection, - msg_.proofHeight, - msg_.proofTry, - channel.counterparty.port_id, - msg_.counterpartyChannelId, - IbcCoreChannelV1Channel.encode(expectedChannel) - ) - ) { - revert IBCChannelLib.ErrInvalidProof(); - } - - channel.state = IbcCoreChannelV1GlobalEnums.State.STATE_OPEN; - channel.version = msg_.counterpartyVersion; - channel.counterparty.channel_id = msg_.counterpartyChannelId; - updateChannelCommitment(msg_.portId, msg_.channelId); - - lookupModuleByPort(msg_.portId).onChanOpenAck( - msg_.portId, - msg_.channelId, - msg_.counterpartyChannelId, - msg_.counterpartyVersion, - msg_.relayer - ); - } - - /** - * @dev channelOpenConfirm is called by the counterparty module to close their end of the channel, since the other end has been closed. - */ - function channelOpenConfirm(IBCMsgs.MsgChannelOpenConfirm calldata msg_) - external - override - { - IbcCoreChannelV1Channel.Data storage channel = - channels[msg_.portId][msg_.channelId]; - if (channel.state != IbcCoreChannelV1GlobalEnums.State.STATE_TRYOPEN) { - revert IBCChannelLib.ErrInvalidChannelState(); - } - - emit IBCChannelLib.ChannelOpenConfirm( - msg_.portId, - msg_.channelId, - channel.counterparty.port_id, - channel.counterparty.channel_id, - channel.connection_hops[0] - ); - - IbcCoreConnectionV1ConnectionEnd.Data memory connection = - ensureConnectionState(channel.connection_hops[0]); - - IbcCoreChannelV1Counterparty.Data memory expectedCounterparty = - IbcCoreChannelV1Counterparty.Data({ - port_id: msg_.portId, - channel_id: msg_.channelId - }); - IbcCoreChannelV1Channel.Data memory expectedChannel = - IbcCoreChannelV1Channel.Data({ - state: IbcCoreChannelV1GlobalEnums.State.STATE_OPEN, - ordering: channel.ordering, - counterparty: expectedCounterparty, - connection_hops: getCounterpartyHops(channel.connection_hops[0]), - version: channel.version - }); - - if ( - !verifyChannelState( - connection, - msg_.proofHeight, - msg_.proofAck, - channel.counterparty.port_id, - channel.counterparty.channel_id, - IbcCoreChannelV1Channel.encode(expectedChannel) - ) - ) { - revert IBCChannelLib.ErrInvalidProof(); - } - - channel.state = IbcCoreChannelV1GlobalEnums.State.STATE_OPEN; - updateChannelCommitment(msg_.portId, msg_.channelId); - - lookupModuleByPort(msg_.portId).onChanOpenConfirm( - msg_.portId, msg_.channelId, msg_.relayer - ); - } - - /** - * @dev channelCloseInit is called by either module to close their end of the channel. Once closed, channels cannot be reopened. - */ - function channelCloseInit(IBCMsgs.MsgChannelCloseInit calldata msg_) - external - override - { - IbcCoreChannelV1Channel.Data storage channel = - channels[msg_.portId][msg_.channelId]; - if (channel.state != IbcCoreChannelV1GlobalEnums.State.STATE_OPEN) { - revert IBCChannelLib.ErrInvalidChannelState(); - } - - ensureConnectionState(channel.connection_hops[0]); - - channel.state = IbcCoreChannelV1GlobalEnums.State.STATE_CLOSED; - updateChannelCommitment(msg_.portId, msg_.channelId); - - lookupModuleByPort(msg_.portId).onChanCloseInit( - msg_.portId, msg_.channelId, msg_.relayer - ); - - emit IBCChannelLib.ChannelCloseInit(msg_.channelId, msg_.portId); - } - - /** - * @dev channelCloseConfirm is called by the counterparty module to close their end of the - * channel, since the other end has been closed. - */ - function channelCloseConfirm(IBCMsgs.MsgChannelCloseConfirm calldata msg_) - external - override - { - IbcCoreChannelV1Channel.Data storage channel = - channels[msg_.portId][msg_.channelId]; - if (channel.state != IbcCoreChannelV1GlobalEnums.State.STATE_OPEN) { - revert IBCChannelLib.ErrInvalidChannelState(); - } - - IbcCoreConnectionV1ConnectionEnd.Data memory connection = - ensureConnectionState(channel.connection_hops[0]); - - IbcCoreChannelV1Counterparty.Data memory expectedCounterparty = - IbcCoreChannelV1Counterparty.Data({ - port_id: msg_.portId, - channel_id: msg_.channelId - }); - IbcCoreChannelV1Channel.Data memory expectedChannel = - IbcCoreChannelV1Channel.Data({ - state: IbcCoreChannelV1GlobalEnums.State.STATE_CLOSED, - ordering: channel.ordering, - counterparty: expectedCounterparty, - connection_hops: getCounterpartyHops(channel.connection_hops[0]), - version: channel.version - }); - - if ( - !verifyChannelState( - connection, - msg_.proofHeight, - msg_.proofInit, - channel.counterparty.port_id, - channel.counterparty.channel_id, - IbcCoreChannelV1Channel.encode(expectedChannel) - ) - ) { - revert IBCChannelLib.ErrInvalidProof(); - } - - channel.state = IbcCoreChannelV1GlobalEnums.State.STATE_CLOSED; - updateChannelCommitment(msg_.portId, msg_.channelId); - - lookupModuleByPort(msg_.portId).onChanCloseConfirm( - msg_.portId, msg_.channelId, msg_.relayer - ); - - emit IBCChannelLib.ChannelCloseConfirm(msg_.channelId, msg_.portId); - } - - function updateChannelCommitment( - string memory portId, - string memory channelId - ) private { - commitments[IBCCommitment.channelCommitmentKey(portId, channelId)] = - keccak256(IbcCoreChannelV1Channel.encode(channels[portId][channelId])); - } - - /* Verification functions */ - - function verifyChannelState( - IbcCoreConnectionV1ConnectionEnd.Data memory connection, - IbcCoreClientV1Height.Data calldata height, - bytes calldata proof, - string memory portId, - string memory channelId, - bytes memory channelBytes - ) private returns (bool) { - return getClient(connection.client_id).verifyMembership( - connection.client_id, - height, - 0, - 0, - proof, - connection.counterparty.prefix.key_prefix, - IBCCommitment.channelPath(portId, channelId), - channelBytes - ); - } - - /* Internal functions */ - - function getCounterpartyHops(string memory connectionId) - internal - view - returns (string[] memory hops) - { - hops = new string[](1); - hops[0] = connections[connectionId].counterparty.connection_id; - return hops; - } - - function generateChannelIdentifier() internal returns (string memory) { - uint256 nextChannelSequence = - uint256(commitments[nextChannelSequencePath]); - - string memory identifier = string( - abi.encodePacked("channel-", Strings.toString(nextChannelSequence)) - ); - commitments[nextChannelSequencePath] = bytes32(nextChannelSequence + 1); - return identifier; - } - - function ensureConnectionState(string memory connectionId) - internal - view - returns (IbcCoreConnectionV1ConnectionEnd.Data memory) - { - IbcCoreConnectionV1ConnectionEnd.Data memory connection = - connections[connectionId]; - if (connection.state != IbcCoreConnectionV1GlobalEnums.State.STATE_OPEN) - { - revert IBCChannelLib.ErrInvalidConnectionState(); - } - return connection; - } - - function ensureConnectionFeature( - string[] calldata connectionHops, - IbcCoreChannelV1GlobalEnums.Order ordering - ) - internal - view - returns (string memory, IbcCoreConnectionV1ConnectionEnd.Data memory) - { - if (connectionHops.length != 1) { - revert IBCChannelLib.ErrConnNotSingleHop(); - } - string memory connectionId = connectionHops[0]; - IbcCoreConnectionV1ConnectionEnd.Data memory connection = - ensureConnectionState(connectionId); - if (connection.versions.length != 1) { - revert IBCChannelLib.ErrConnNotSingleVersion(); - } - if ( - !IBCChannelLib.verifySupportedFeature( - connection.versions[0], IBCChannelLib.toString(ordering) - ) - ) { - revert IBCChannelLib.ErrUnsupportedFeature(); - } - return (connectionId, connection); - } -} diff --git a/evm/contracts/core/04-channel/IBCPacket.sol b/evm/contracts/core/04-channel/IBCPacket.sol index 90d76add50..fe6fa55422 100644 --- a/evm/contracts/core/04-channel/IBCPacket.sol +++ b/evm/contracts/core/04-channel/IBCPacket.sol @@ -1,34 +1,27 @@ pragma solidity ^0.8.23; -import "solady/utils/LibString.sol"; -import "@openzeppelin/utils/Strings.sol"; - -import "../../proto/ibc/core/channel/v1/channel.sol"; +import "../24-host/IBCStore.sol"; import "../25-handler/IBCMsgs.sol"; import "../02-client/IBCHeight.sol"; import "../24-host/IBCStore.sol"; import "../24-host/IBCCommitment.sol"; import "../04-channel/IIBCPacket.sol"; -import "../05-port/ModuleManager.sol"; import "../05-port/IIBCModule.sol"; +import "../Types.sol"; library IBCPacketLib { event SendPacket( uint64 sequence, - string sourcePort, - string sourceChannel, - IbcCoreClientV1Height.Data timeoutHeight, + address sourcePort, + uint32 sourceChannel, + IBCHeight timeoutHeight, uint64 timeoutTimestamp, bytes data ); - event RecvPacket(IbcCoreChannelV1Packet.Data packet); - event WriteAcknowledgement( - IbcCoreChannelV1Packet.Data packet, bytes acknowledgement - ); - event AcknowledgePacket( - IbcCoreChannelV1Packet.Data packet, bytes acknowledgement - ); - event TimeoutPacket(IbcCoreChannelV1Packet.Data packet); + event RecvPacket(IBCPacket packet); + event WriteAcknowledgement(IBCPacket packet, bytes acknowledgement); + event AcknowledgePacket(IBCPacket packet, bytes acknowledgement); + event TimeoutPacket(IBCPacket packet); error ErrUnauthorized(); error ErrInvalidChannelState(); @@ -47,7 +40,6 @@ library IBCPacketLib { error ErrInvalidProof(); error ErrPacketAlreadyReceived(); error ErrPacketSequenceNextSequenceMismatch(); - error ErrUnknownChannelOrdering(); error ErrAcknowledgementIsEmpty(); error ErrAcknowledgementAlreadyExists(); error ErrPacketCommitmentNotFound(); @@ -60,9 +52,8 @@ library IBCPacketLib { /** * @dev IBCPacket is a contract that implements [ICS-4](https://github.com/cosmos/ibc/tree/main/spec/core/ics-004-channel-and-packet-semantics). */ -contract IBCPacket is IBCStore, IIBCPacket, ModuleManager { - using IBCHeight for IbcCoreClientV1Height.Data; - using LibString for *; +abstract contract IBCPacketImpl is IBCStore, IIBCPacket { + using IBCHeightLib for IBCHeight; /** * @dev sendPacket is called by a module in order to send an IBC packet on a channel. @@ -70,84 +61,34 @@ contract IBCPacket is IBCStore, IIBCPacket, ModuleManager { * is returned if one occurs. */ function sendPacket( - string calldata sourceChannel, - IbcCoreClientV1Height.Data calldata timeoutHeight, + uint32 sourceChannel, + IBCHeight calldata timeoutHeight, uint64 timeoutTimestamp, bytes calldata data ) external override returns (uint64) { - string memory sourcePort = msg.sender.toHexString(); - if ( - !authenticateCapability( - channelCapabilityPath(sourcePort, sourceChannel) - ) - ) { + if (!authenticateChannelOwner(sourceChannel)) { revert IBCPacketLib.ErrUnauthorized(); } - - IbcCoreChannelV1Channel.Data storage channel = - ensureChannelState(sourcePort, sourceChannel); - + ensureChannelState(sourceChannel); if (timeoutTimestamp == 0 && timeoutHeight.isZero()) { revert IBCPacketLib.ErrTimeoutMustBeSet(); } - - string memory clientId = - connections[channel.connection_hops[0]].client_id; - ILightClient client = getClient(clientId); - - IbcCoreClientV1Height.Data memory latestHeight = - client.getLatestHeight(clientId); - if (latestHeight.revision_height == 0) { - revert IBCPacketLib.ErrLatestHeightNotFound(); - } - if (!timeoutHeight.isZero() && latestHeight.gte(timeoutHeight)) { - revert IBCPacketLib.ErrInvalidTimeoutHeight(); - } - - uint64 latestTimestamp; - latestTimestamp = client.getTimestampAtHeight(clientId, latestHeight); - if (latestTimestamp == 0) { - revert IBCPacketLib.ErrLatestTimestampNotFound(); - } - if (timeoutTimestamp != 0 && latestTimestamp >= timeoutTimestamp) { - revert IBCPacketLib.ErrInvalidTimeoutTimestamp(); - } - - uint64 packetSequence = uint64( - uint256( - commitments[IBCCommitment.nextSequenceSendCommitmentKey( - sourcePort, sourceChannel - )] - ) - ); - commitments[IBCCommitment.nextSequenceSendCommitmentKey( - sourcePort, sourceChannel - )] = bytes32(uint256(packetSequence + 1)); + address sourcePort = msg.sender; + bytes32 sourcePortNormalized = keccak256(abi.encodePacked(sourcePort)); + uint64 sequence = + generatePacketSequence(sourcePortNormalized, sourceChannel); commitments[IBCCommitment.packetCommitmentKey( - sourcePort, sourceChannel, packetSequence - )] = keccak256( - abi.encodePacked( - sha256( - abi.encodePacked( - timeoutTimestamp, - timeoutHeight.revision_number, - timeoutHeight.revision_height, - sha256(data) - ) - ) - ) - ); - + sourcePortNormalized, sourceChannel, sequence + )] = commitPacket(timeoutTimestamp, timeoutHeight, data); emit IBCPacketLib.SendPacket( - packetSequence, + sequence, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data ); - - return packetSequence; + return sequence; } /** @@ -158,79 +99,56 @@ contract IBCPacket is IBCStore, IIBCPacket, ModuleManager { external override { - IbcCoreChannelV1Channel.Data storage channel = ensureChannelState( - msg_.packet.destination_port, msg_.packet.destination_channel - ); - - if ( - hashString(msg_.packet.source_port) - != hashString(channel.counterparty.port_id) - ) { + IBCChannel storage channel = + ensureChannelState(msg_.packet.destinationChannel); + if (msg_.packet.sourcePort != channel.counterparty.portId) { revert IBCPacketLib.ErrSourceAndCounterpartyPortMismatch(); } - if ( - hashString(msg_.packet.source_channel) - != hashString(channel.counterparty.channel_id) - ) { + if (msg_.packet.sourceChannel != channel.counterparty.channelId) { revert IBCPacketLib.ErrSourceAndCounterpartyChannelMismatch(); } - - IbcCoreConnectionV1ConnectionEnd.Data storage connection = - connections[channel.connection_hops[0]]; - if (connection.state != IbcCoreConnectionV1GlobalEnums.State.STATE_OPEN) - { - revert IBCPacketLib.ErrInvalidConnectionState(); - } - + IBCConnection storage connection = + ensureConnectionState(channel.connectionId); if ( - msg_.packet.timeout_height.revision_height != 0 - && (block.number >= msg_.packet.timeout_height.revision_height) + msg_.packet.timeoutHeight.revisionHeight != 0 + && (block.number >= msg_.packet.timeoutHeight.revisionHeight) ) { revert IBCPacketLib.ErrHeightTimeout(); } - // For some reason cosmos is using nanos, we try to follow their convention to avoid friction uint64 currentTimestamp = uint64(block.timestamp * 1e9); if ( - msg_.packet.timeout_timestamp != 0 - && (currentTimestamp >= msg_.packet.timeout_timestamp) + msg_.packet.timeoutTimestamp != 0 + && (currentTimestamp >= msg_.packet.timeoutTimestamp) ) { revert IBCPacketLib.ErrTimestampTimeout(); } - if ( !verifyCommitment( connection, msg_.proofHeight, msg_.proof, IBCCommitment.packetCommitmentPath( - msg_.packet.source_port, - msg_.packet.source_channel, + msg_.packet.sourcePort, + msg_.packet.sourceChannel, msg_.packet.sequence ), abi.encodePacked( - sha256( - abi.encodePacked( - msg_.packet.timeout_timestamp, - msg_.packet.timeout_height.revision_number, - msg_.packet.timeout_height.revision_height, - sha256(msg_.packet.data) - ) + commitPacket( + msg_.packet.timeoutTimestamp, + msg_.packet.timeoutHeight, + msg_.packet.data ) ) ) ) { revert IBCPacketLib.ErrInvalidProof(); } - - if ( - channel.ordering - == IbcCoreChannelV1GlobalEnums.Order.ORDER_UNORDERED - ) { + if (channel.ordering == IBCChannelOrder.Unordered) { bytes32 receiptCommitmentKey = IBCCommitment .packetReceiptCommitmentKey( - msg_.packet.destination_port, - msg_.packet.destination_channel, + msg_.packet.destinationPort, + msg_.packet.destinationChannel, msg_.packet.sequence ); bytes32 receipt = commitments[receiptCommitmentKey]; @@ -238,14 +156,12 @@ contract IBCPacket is IBCStore, IIBCPacket, ModuleManager { revert IBCPacketLib.ErrPacketAlreadyReceived(); } commitments[receiptCommitmentKey] = bytes32(uint256(1)); - } else if ( - channel.ordering == IbcCoreChannelV1GlobalEnums.Order.ORDER_ORDERED - ) { + } else if (channel.ordering == IBCChannelOrder.Ordered) { uint64 expectedRecvSequence = uint64( uint256( commitments[IBCCommitment.nextSequenceRecvCommitmentKey( - msg_.packet.destination_port, - msg_.packet.destination_channel + msg_.packet.destinationPort, + msg_.packet.destinationChannel )] ) ); @@ -253,17 +169,12 @@ contract IBCPacket is IBCStore, IIBCPacket, ModuleManager { revert IBCPacketLib.ErrPacketSequenceNextSequenceMismatch(); } commitments[IBCCommitment.nextSequenceRecvCommitmentKey( - msg_.packet.destination_port, msg_.packet.destination_channel + msg_.packet.destinationPort, msg_.packet.destinationChannel )] = bytes32(uint256(expectedRecvSequence + 1)); - } else { - revert IBCPacketLib.ErrUnknownChannelOrdering(); } - - IIBCModule module = lookupModuleByChannel( - msg_.packet.destination_port, msg_.packet.destination_channel - ); - bytes memory acknowledgement = - module.onRecvPacket(msg_.packet, msg_.relayer); + bytes memory acknowledgement = lookupModuleByChannel( + msg_.packet.destinationChannel + ).onRecvPacket(msg_.packet, msg_.relayer); if (acknowledgement.length > 0) { _writeAcknowledgement(msg_.packet, acknowledgement); } @@ -271,18 +182,12 @@ contract IBCPacket is IBCStore, IIBCPacket, ModuleManager { } function _writeAcknowledgement( - IbcCoreChannelV1Packet.Data calldata packet, + IBCPacket calldata packet, bytes memory acknowledgement ) internal { - if (acknowledgement.length == 0) { - revert IBCPacketLib.ErrAcknowledgementIsEmpty(); - } - - ensureChannelState(packet.destination_port, packet.destination_channel); - bytes32 ackCommitmentKey = IBCCommitment .packetAcknowledgementCommitmentKey( - packet.destination_port, packet.destination_channel, packet.sequence + packet.destinationPort, packet.destinationChannel, packet.sequence ); bytes32 ackCommitment = commitments[ackCommitmentKey]; if (ackCommitment != bytes32(0)) { @@ -290,7 +195,6 @@ contract IBCPacket is IBCStore, IIBCPacket, ModuleManager { } commitments[ackCommitmentKey] = keccak256(abi.encodePacked(sha256(acknowledgement))); - emit IBCPacketLib.WriteAcknowledgement(packet, acknowledgement); } @@ -299,19 +203,16 @@ contract IBCPacket is IBCStore, IIBCPacket, ModuleManager { * which will be verified by the counterparty chain using AcknowledgePacket. */ function writeAcknowledgement( - IbcCoreChannelV1Packet.Data calldata packet, + IBCPacket calldata packet, bytes memory acknowledgement ) external override { - string memory destinationPort = msg.sender.toHexString(); - if ( - !authenticateCapability( - channelCapabilityPath( - destinationPort, packet.destination_channel - ) - ) - ) { + if (acknowledgement.length == 0) { + revert IBCPacketLib.ErrAcknowledgementIsEmpty(); + } + if (!authenticateChannelOwner(packet.destinationChannel)) { revert IBCPacketLib.ErrUnauthorized(); } + ensureChannelState(packet.destinationChannel); _writeAcknowledgement(packet, acknowledgement); } @@ -327,77 +228,38 @@ contract IBCPacket is IBCStore, IIBCPacket, ModuleManager { external override { - IbcCoreChannelV1Channel.Data storage channel = ensureChannelState( - msg_.packet.source_port, msg_.packet.source_channel - ); - - if ( - hashString(msg_.packet.destination_port) - != hashString(channel.counterparty.port_id) - ) { + IBCChannel storage channel = + ensureChannelState(msg_.packet.sourceChannel); + if (msg_.packet.destinationPort != channel.counterparty.portId) { revert IBCPacketLib.ErrDestinationAndCounterpartyPortMismatch(); } - if ( - hashString(msg_.packet.destination_channel) - != hashString(channel.counterparty.channel_id) - ) { + if (msg_.packet.destinationChannel != channel.counterparty.channelId) { revert IBCPacketLib.ErrDestinationAndCounterpartyChannelMismatch(); } - - IbcCoreConnectionV1ConnectionEnd.Data storage connection = - connections[channel.connection_hops[0]]; - if (connection.state != IbcCoreConnectionV1GlobalEnums.State.STATE_OPEN) - { - revert IBCPacketLib.ErrInvalidConnectionState(); - } - - bytes32 packetCommitmentKey = IBCCommitment.packetCommitmentKey( - msg_.packet.source_port, - msg_.packet.source_channel, - msg_.packet.sequence - ); - bytes32 expectedPacketCommitment = commitments[packetCommitmentKey]; - if (expectedPacketCommitment == bytes32(0)) { - revert IBCPacketLib.ErrPacketCommitmentNotFound(); - } - bytes32 packetCommitment = keccak256( - abi.encodePacked( - sha256( - abi.encodePacked( - msg_.packet.timeout_timestamp, - msg_.packet.timeout_height.revision_number, - msg_.packet.timeout_height.revision_height, - sha256(msg_.packet.data) - ) - ) - ) - ); - if (expectedPacketCommitment != packetCommitment) { - revert IBCPacketLib.ErrInvalidPacketCommitment(); - } - + IBCConnection storage connection = + ensureConnectionState(channel.connectionId); + bytes32 packetCommitmentKey = ensurePacketCommitment(msg_.packet); + delete commitments[packetCommitmentKey]; if ( !verifyCommitment( connection, msg_.proofHeight, msg_.proof, IBCCommitment.packetAcknowledgementCommitmentPath( - msg_.packet.destination_port, - msg_.packet.destination_channel, + msg_.packet.destinationPort, + msg_.packet.destinationChannel, msg_.packet.sequence ), - abi.encodePacked(sha256(msg_.acknowledgement)) + abi.encodePacked(keccak256(msg_.acknowledgement)) ) ) { revert IBCPacketLib.ErrInvalidProof(); } - - if (channel.ordering == IbcCoreChannelV1GlobalEnums.Order.ORDER_ORDERED) - { + if (channel.ordering == IBCChannelOrder.Ordered) { uint64 expectedAckSequence = uint64( uint256( commitments[IBCCommitment.nextSequenceAckCommitmentKey( - msg_.packet.source_port, msg_.packet.source_channel + msg_.packet.sourcePort, msg_.packet.sourceChannel )] ) ); @@ -405,104 +267,50 @@ contract IBCPacket is IBCStore, IIBCPacket, ModuleManager { revert IBCPacketLib.ErrPacketSequenceNextSequenceMismatch(); } commitments[IBCCommitment.nextSequenceAckCommitmentKey( - msg_.packet.source_port, msg_.packet.source_channel + msg_.packet.sourcePort, msg_.packet.sourceChannel )] = bytes32(uint256(expectedAckSequence + 1)); } - - delete commitments[packetCommitmentKey]; - - IIBCModule module = lookupModuleByChannel( - msg_.packet.source_port, msg_.packet.source_channel - ); - module.onAcknowledgementPacket( + lookupModuleByChannel(msg_.packet.sourceChannel).onAcknowledgementPacket( msg_.packet, msg_.acknowledgement, msg_.relayer ); - emit IBCPacketLib.AcknowledgePacket(msg_.packet, msg_.acknowledgement); } - function hashString(string memory s) private pure returns (bytes32) { - return keccak256(abi.encodePacked(s)); - } - function timeoutPacket(IBCMsgs.MsgPacketTimeout calldata msg_) external override { - IbcCoreChannelV1Channel.Data storage channel = ensureChannelState( - msg_.packet.source_port, msg_.packet.source_channel - ); - - if ( - hashString(msg_.packet.destination_port) - != hashString(channel.counterparty.port_id) - ) { + IBCChannel storage channel = + ensureChannelState(msg_.packet.sourceChannel); + if (msg_.packet.destinationPort != channel.counterparty.portId) { revert IBCPacketLib.ErrDestinationAndCounterpartyPortMismatch(); } - if ( - hashString(msg_.packet.destination_channel) - != hashString(channel.counterparty.channel_id) - ) { + if (msg_.packet.destinationChannel != channel.counterparty.channelId) { revert IBCPacketLib.ErrDestinationAndCounterpartyChannelMismatch(); } - - IbcCoreConnectionV1ConnectionEnd.Data storage connection = - connections[channel.connection_hops[0]]; - if (connection.state != IbcCoreConnectionV1GlobalEnums.State.STATE_OPEN) - { - revert IBCPacketLib.ErrInvalidConnectionState(); - } - - bytes32 packetCommitmentKey = IBCCommitment.packetCommitmentKey( - msg_.packet.source_port, - msg_.packet.source_channel, - msg_.packet.sequence - ); - bytes32 expectedPacketCommitment = commitments[packetCommitmentKey]; - if (expectedPacketCommitment == bytes32(0)) { - revert IBCPacketLib.ErrPacketCommitmentNotFound(); - } - bytes32 packetCommitment = keccak256( - abi.encodePacked( - sha256( - abi.encodePacked( - msg_.packet.timeout_timestamp, - msg_.packet.timeout_height.revision_number, - msg_.packet.timeout_height.revision_height, - sha256(msg_.packet.data) - ) - ) - ) - ); - if (expectedPacketCommitment != packetCommitment) { - revert IBCPacketLib.ErrInvalidPacketCommitment(); - } - - ILightClient client = getClient(connection.client_id); + IBCConnection storage connection = + ensureConnectionState(channel.connectionId); + bytes32 packetCommitmentKey = ensurePacketCommitment(msg_.packet); + delete commitments[packetCommitmentKey]; + ILightClient client = getClientInternal(connection.clientId); uint64 proofTimestamp = - client.getTimestampAtHeight(connection.client_id, msg_.proofHeight); + client.getTimestampAtHeight(connection.clientId, msg_.proofHeight); if (proofTimestamp == 0) { revert IBCPacketLib.ErrLatestTimestampNotFound(); } - if ( - msg_.packet.timeout_timestamp > 0 - && msg_.packet.timeout_timestamp >= proofTimestamp + msg_.packet.timeoutTimestamp > 0 + && msg_.packet.timeoutTimestamp >= proofTimestamp ) { revert IBCPacketLib.ErrTimeoutTimestampNotReached(); } if ( - !msg_.packet.timeout_height.isZero() - && msg_.packet.timeout_height.gte(msg_.proofHeight) + !msg_.packet.timeoutHeight.isZero() + && msg_.packet.timeoutHeight.gte(msg_.proofHeight) ) { revert IBCPacketLib.ErrTimeoutHeightNotReached(); } - - bool isOrdered = - channel.ordering == IbcCoreChannelV1GlobalEnums.Order.ORDER_ORDERED; - bool isUnordered = channel.ordering - == IbcCoreChannelV1GlobalEnums.Order.ORDER_UNORDERED; - if (isOrdered) { + if (channel.ordering == IBCChannelOrder.Ordered) { if (msg_.nextSequenceRecv <= msg_.packet.sequence) { revert IBCPacketLib @@ -514,89 +322,134 @@ contract IBCPacket is IBCStore, IIBCPacket, ModuleManager { msg_.proofHeight, msg_.proof, IBCCommitment.nextSequenceRecvCommitmentPath( - msg_.packet.destination_port, - msg_.packet.destination_channel + msg_.packet.destinationPort, + msg_.packet.destinationChannel ), abi.encodePacked(msg_.nextSequenceRecv) ) ) { revert IBCPacketLib.ErrInvalidProof(); } - channel.state = IbcCoreChannelV1GlobalEnums.State.STATE_CLOSED; - } else if (isUnordered) { + } else if (channel.ordering == IBCChannelOrder.Unordered) { if ( !verifyAbsentCommitment( connection, msg_.proofHeight, msg_.proof, IBCCommitment.packetReceiptCommitmentPath( - msg_.packet.destination_port, - msg_.packet.destination_channel, + msg_.packet.destinationPort, + msg_.packet.destinationChannel, msg_.packet.sequence ) ) ) { revert IBCPacketLib.ErrInvalidProof(); } - } else { - revert IBCPacketLib.ErrUnknownChannelOrdering(); } - - delete commitments[packetCommitmentKey]; - - IIBCModule module = lookupModuleByChannel( - msg_.packet.source_port, msg_.packet.source_channel + lookupModuleByChannel(msg_.packet.sourceChannel).onTimeoutPacket( + msg_.packet, msg_.relayer ); - module.onTimeoutPacket(msg_.packet, msg_.relayer); - emit IBCPacketLib.TimeoutPacket(msg_.packet); } function verifyCommitment( - IbcCoreConnectionV1ConnectionEnd.Data storage connection, - IbcCoreClientV1Height.Data calldata height, + IBCConnection storage connection, + IBCHeight calldata height, bytes calldata proof, bytes memory path, bytes memory commitment - ) private returns (bool) { - return getClient(connection.client_id).verifyMembership( - connection.client_id, + ) internal returns (bool) { + return getClientInternal(connection.clientId).verifyMembership( + connection.clientId, height, - connection.delay_period, + connection.delayPeriod, 0, proof, - connection.counterparty.prefix.key_prefix, + abi.encodePacked(connection.counterparty.merklePrefix), path, commitment ); } function verifyAbsentCommitment( - IbcCoreConnectionV1ConnectionEnd.Data storage connection, - IbcCoreClientV1Height.Data calldata height, + IBCConnection storage connection, + IBCHeight calldata height, bytes calldata proof, bytes memory path - ) private returns (bool) { - return getClient(connection.client_id).verifyNonMembership( - connection.client_id, + ) internal returns (bool) { + return getClientInternal(connection.clientId).verifyNonMembership( + connection.clientId, height, - connection.delay_period, + connection.delayPeriod, 0, proof, - connection.counterparty.prefix.key_prefix, + abi.encodePacked(connection.counterparty.merklePrefix), path ); } - function ensureChannelState( - string memory portId, - string calldata channelId - ) internal view returns (IbcCoreChannelV1Channel.Data storage) { - IbcCoreChannelV1Channel.Data storage channel = - channels[portId][channelId]; - if (channel.state != IbcCoreChannelV1GlobalEnums.State.STATE_OPEN) { + function ensureChannelState(uint32 channelId) + internal + view + returns (IBCChannel storage) + { + IBCChannel storage channel = channels[channelId]; + if (channel.state != IBCChannelState.Open) { revert IBCPacketLib.ErrInvalidChannelState(); } return channel; } + + function generatePacketSequence( + bytes32 portId, + uint32 channelId + ) internal returns (uint64) { + uint64 seq = uint64( + uint256( + commitments[IBCCommitment.nextSequenceSendCommitmentKey( + portId, channelId + )] + ) + ); + commitments[IBCCommitment.nextSequenceSendCommitmentKey( + portId, channelId + )] = bytes32(uint256(seq + 1)); + return seq; + } + + function ensurePacketCommitment(IBCPacket calldata packet) + internal + view + returns (bytes32) + { + bytes32 packetCommitmentKey = IBCCommitment.packetCommitmentKey( + packet.sourcePort, packet.sourceChannel, packet.sequence + ); + bytes32 expectedPacketCommitment = commitments[packetCommitmentKey]; + if (expectedPacketCommitment == bytes32(0)) { + revert IBCPacketLib.ErrPacketCommitmentNotFound(); + } + bytes32 packetCommitment = commitPacket( + packet.timeoutTimestamp, packet.timeoutHeight, packet.data + ); + if (expectedPacketCommitment != packetCommitment) { + revert IBCPacketLib.ErrInvalidPacketCommitment(); + } + return packetCommitmentKey; + } + + function commitPacket( + uint64 timeoutTimestamp, + IBCHeight calldata timeoutHeight, + bytes calldata data + ) internal pure returns (bytes32) { + return keccak256( + abi.encodePacked( + timeoutTimestamp, + timeoutHeight.revisionNumber, + timeoutHeight.revisionHeight, + data + ) + ); + } } diff --git a/evm/contracts/core/04-channel/IIBCChannel.sol b/evm/contracts/core/04-channel/IIBCChannel.sol index 970b3eeee8..22e982fc45 100644 --- a/evm/contracts/core/04-channel/IIBCChannel.sol +++ b/evm/contracts/core/04-channel/IIBCChannel.sol @@ -2,20 +2,20 @@ pragma solidity ^0.8.23; import "../25-handler/IBCMsgs.sol"; -interface IIBCChannelHandshake { +interface IIBCChannel { /** * @dev channelOpenInit is called by a module to initiate a channel opening handshake with a module on another chain. */ function channelOpenInit(IBCMsgs.MsgChannelOpenInit calldata msg_) external - returns (string memory); + returns (uint32); /** * @dev channelOpenTry is called by a module to accept the first step of a channel opening handshake initiated by a module on another chain. */ function channelOpenTry(IBCMsgs.MsgChannelOpenTry calldata msg_) external - returns (string memory); + returns (uint32); /** * @dev channelOpenAck is called by the handshake-originating module to acknowledge the acceptance of the initial request by the counterparty module on the other chain. diff --git a/evm/contracts/core/04-channel/IIBCPacket.sol b/evm/contracts/core/04-channel/IIBCPacket.sol index c0f336d4a3..efad804be5 100644 --- a/evm/contracts/core/04-channel/IIBCPacket.sol +++ b/evm/contracts/core/04-channel/IIBCPacket.sol @@ -9,8 +9,8 @@ interface IIBCPacket { * is returned if one occurs. */ function sendPacket( - string calldata sourceChannel, - IbcCoreClientV1Height.Data calldata timeoutHeight, + uint32 sourceChannel, + IBCHeight calldata timeoutHeight, uint64 timeoutTimestamp, bytes calldata data ) external returns (uint64); @@ -26,7 +26,7 @@ interface IIBCPacket { * which will be verified by the counterparty chain using AcknowledgePacket. */ function writeAcknowledgement( - IbcCoreChannelV1Packet.Data calldata packet, + IBCPacket calldata packet, bytes memory acknowledgement ) external; diff --git a/evm/contracts/core/05-port/IIBCModule.sol b/evm/contracts/core/05-port/IIBCModule.sol index b771206156..d8d98a5964 100644 --- a/evm/contracts/core/05-port/IIBCModule.sol +++ b/evm/contracts/core/05-port/IIBCModule.sol @@ -1,71 +1,53 @@ pragma solidity ^0.8.23; -import "../../proto/ibc/core/channel/v1/channel.sol"; +import "../Types.sol"; // IIBCModule defines an interface that implements all the callbacks // that modules must define as specified in ICS-26 // https://github.com/cosmos/ibc/blob/2921c5cec7b18e4ef77677e16a6b693051ae3b35/spec/core/ics-026-routing-module/README.md interface IIBCModule { function onChanOpenInit( - IbcCoreChannelV1GlobalEnums.Order, - string[] calldata connectionHops, - string calldata portId, - string calldata channelId, - IbcCoreChannelV1Counterparty.Data calldata counterparty, - string calldata version, + IBCChannelOrder, + uint32 connectionId, + uint32 channelId, + IBCChannelCounterparty calldata counterparty, + bytes32 version, address relayer ) external; function onChanOpenTry( - IbcCoreChannelV1GlobalEnums.Order, - string[] calldata connectionHops, - string calldata portId, - string calldata channelId, - IbcCoreChannelV1Counterparty.Data calldata counterparty, - string calldata version, - string calldata counterpartyVersion, + IBCChannelOrder, + uint32 connectionId, + uint32 channelId, + IBCChannelCounterparty calldata counterparty, + bytes32 version, + bytes32 counterpartyVersion, address relayer ) external; function onChanOpenAck( - string calldata portId, - string calldata channelId, - string calldata counterpartyChannelId, - string calldata counterpartyVersion, + uint32 channelId, + uint32 counterpartyChannelId, + bytes32 counterpartyVersion, address relayer ) external; - function onChanOpenConfirm( - string calldata portId, - string calldata channelId, - address relayer - ) external; + function onChanOpenConfirm(uint32 channelId, address relayer) external; - function onChanCloseInit( - string calldata portId, - string calldata channelId, - address relayer - ) external; + function onChanCloseInit(uint32 channelId, address relayer) external; - function onChanCloseConfirm( - string calldata portId, - string calldata channelId, - address relayer - ) external; + function onChanCloseConfirm(uint32 channelId, address relayer) external; function onRecvPacket( - IbcCoreChannelV1Packet.Data calldata, + IBCPacket calldata, address relayer ) external returns (bytes memory); function onAcknowledgementPacket( - IbcCoreChannelV1Packet.Data calldata, + IBCPacket calldata, bytes calldata acknowledgement, address relayer ) external; - function onTimeoutPacket( - IbcCoreChannelV1Packet.Data calldata, - address relayer - ) external; + function onTimeoutPacket(IBCPacket calldata, address relayer) external; } diff --git a/evm/contracts/core/05-port/ModuleManager.sol b/evm/contracts/core/05-port/ModuleManager.sol deleted file mode 100644 index a1fb80bb8f..0000000000 --- a/evm/contracts/core/05-port/ModuleManager.sol +++ /dev/null @@ -1,80 +0,0 @@ -pragma solidity ^0.8.23; - -import "./IIBCModule.sol"; -import "../24-host/IBCStore.sol"; -import "../../lib/Hex.sol"; - -library ModuleManagerLib { - error ErrModuleNotFound(); - error ErrCapabilityAlreadyClaimed(); -} - -/** - * @dev ModuleManager is an abstract contract that provides the functions defined in [ICS 5](https://github.com/cosmos/ibc/tree/main/spec/core/ics-005-port-allocation) and [ICS 26](https://github.com/cosmos/ibc/blob/main/spec/core/ics-005-port-module/README.md). - */ -abstract contract ModuleManager is IBCStore { - /** - * @dev lookupModuleByPort will return the IBCModule along with the capability associated with a given portID - */ - function lookupModuleByPort(string memory portId) - internal - view - virtual - returns (IIBCModule) - { - return IIBCModule(Hex.hexToAddress(portId)); - } - - /** - * @dev lookupModuleByChannel will return the IBCModule along with the capability associated with a given channel defined by its portID and channelID - */ - function lookupModuleByChannel( - string memory portId, - string memory channelId - ) internal view virtual returns (IIBCModule) { - address module = lookupModule(channelCapabilityPath(portId, channelId)); - if (module == address(0)) { - revert ModuleManagerLib.ErrModuleNotFound(); - } - return IIBCModule(module); - } - - /** - * @dev channelCapabilityPath returns the path under which module address associated with a port and channel should be stored. - */ - function channelCapabilityPath( - string memory portId, - string memory channelId - ) public pure returns (string memory) { - return string.concat(portId, "/", channelId); - } - - /** - * @dev claimCapability allows the IBC app module to claim a capability that core IBC passes to it - */ - function claimCapability(string memory name, address addr) internal { - if (capabilities[name] != address(0)) { - revert ModuleManagerLib.ErrCapabilityAlreadyClaimed(); - } - capabilities[name] = addr; - } - - /** - * @dev authenticateCapability attempts to authenticate a given name from a caller. - * It allows for a caller to check that a capability does in fact correspond to a particular name. - */ - function authenticateCapability(string memory name) - internal - view - returns (bool) - { - return msg.sender == capabilities[name]; - } - - /** - * @dev lookupModule will return the IBCModule address bound to a given name. - */ - function lookupModule(string memory name) internal view returns (address) { - return capabilities[name]; - } -} diff --git a/evm/contracts/core/24-host/IBCCommitment.sol b/evm/contracts/core/24-host/IBCCommitment.sol index e7f880c980..419e5fb2fc 100644 --- a/evm/contracts/core/24-host/IBCCommitment.sol +++ b/evm/contracts/core/24-host/IBCCommitment.sol @@ -3,123 +3,98 @@ pragma solidity ^0.8.23; import "solady/utils/LibString.sol"; library IBCCommitment { - // Commitment path generators that comply with https://github.com/cosmos/ibc/tree/main/spec/core/ics-024-host-requirements#path-space - - function clientStatePath(string memory clientId) + bytes1 public constant CLIENT_STATE = 0x00; + bytes1 public constant CONSENSUS_STATE = 0x01; + bytes1 public constant CONNECTIONS = 0x02; + bytes1 public constant CHANNELS = 0x05; + bytes1 public constant PACKETS = 0x06; + bytes1 public constant PACKET_ACKS = 0x07; + bytes1 public constant PACKET_RECEIPTS = 0x08; + bytes1 public constant NEXT_SEQ_SEND = 0x09; + bytes1 public constant NEXT_SEQ_RECV = 0x0A; + bytes1 public constant NEXT_SEQ_ACK = 0x0B; + + function clientStatePath(uint32 clientId) internal pure returns (bytes memory) { - return abi.encodePacked("clients/", clientId, "/clientState"); + return abi.encodePacked(CLIENT_STATE, clientId); } function consensusStatePath( - string memory clientId, + uint32 clientId, uint64 revisionNumber, uint64 revisionHeight ) internal pure returns (bytes memory) { return abi.encodePacked( - "clients/", - clientId, - "/consensusStates/", - LibString.toString(revisionNumber), - "-", - LibString.toString(revisionHeight) + CONSENSUS_STATE, clientId, revisionNumber, revisionHeight ); } - function connectionPath(string memory connectionId) + function connectionPath(uint32 connectionId) internal pure returns (bytes memory) { - return abi.encodePacked("connections/", connectionId); + return abi.encodePacked(CONNECTIONS, connectionId); } function channelPath( - string memory portId, - string memory channelId + bytes32 portId, + uint32 channelId ) internal pure returns (bytes memory) { - return abi.encodePacked( - "channelEnds/ports/", portId, "/channels/", channelId - ); + return abi.encodePacked(CHANNELS, portId, channelId); } function packetCommitmentPath( - string memory portId, - string memory channelId, + bytes32 portId, + uint32 channelId, uint64 sequence ) internal pure returns (bytes memory) { - return abi.encodePacked( - "commitments/ports/", - portId, - "/channels/", - channelId, - "/sequences/", - LibString.toString(sequence) - ); + return abi.encodePacked(PACKETS, portId, channelId, sequence); } function packetAcknowledgementCommitmentPath( - string memory portId, - string memory channelId, + bytes32 portId, + uint32 channelId, uint64 sequence ) internal pure returns (bytes memory) { - return abi.encodePacked( - "acks/ports/", - portId, - "/channels/", - channelId, - "/sequences/", - LibString.toString(sequence) - ); + return abi.encodePacked(PACKET_ACKS, portId, channelId, sequence); } function packetReceiptCommitmentPath( - string memory portId, - string memory channelId, + bytes32 portId, + uint32 channelId, uint64 sequence ) internal pure returns (bytes memory) { - return abi.encodePacked( - "receipts/ports/", - portId, - "/channels/", - channelId, - "/sequences/", - LibString.toString(sequence) - ); + return abi.encodePacked(PACKET_RECEIPTS, portId, channelId, sequence); } function nextSequenceSendCommitmentPath( - string memory portId, - string memory channelId + bytes32 portId, + uint32 channelId ) internal pure returns (bytes memory) { - return abi.encodePacked( - "nextSequenceSend/ports/", portId, "/channels/", channelId - ); + return abi.encodePacked(NEXT_SEQ_SEND, portId, channelId); } function nextSequenceRecvCommitmentPath( - string memory portId, - string memory channelId + bytes32 portId, + uint32 channelId ) internal pure returns (bytes memory) { - return abi.encodePacked( - "nextSequenceRecv/ports/", portId, "/channels/", channelId - ); + return abi.encodePacked(NEXT_SEQ_RECV, portId, channelId); } function nextSequenceAckCommitmentPath( - string memory portId, - string memory channelId + bytes32 portId, + uint32 channelId ) internal pure returns (bytes memory) { - return abi.encodePacked( - "nextSequenceAck/ports/", portId, "/channels/", channelId - ); + return abi.encodePacked(NEXT_SEQ_ACK, portId, channelId); } // Key generators for Commitment mapping - function clientStateCommitmentKey(string memory clientId) + function clientStateCommitmentKey(uint32 clientId) internal pure returns (bytes32) @@ -128,7 +103,7 @@ library IBCCommitment { } function consensusStateCommitmentKey( - string memory clientId, + uint32 clientId, uint64 revisionNumber, uint64 revisionHeight ) internal pure returns (bytes32) { @@ -137,7 +112,7 @@ library IBCCommitment { ); } - function connectionCommitmentKey(string memory connectionId) + function connectionCommitmentKey(uint32 connectionId) internal pure returns (bytes32) @@ -146,23 +121,23 @@ library IBCCommitment { } function channelCommitmentKey( - string memory portId, - string memory channelId + bytes32 portId, + uint32 channelId ) internal pure returns (bytes32) { return keccak256(channelPath(portId, channelId)); } function packetCommitmentKey( - string memory portId, - string memory channelId, + bytes32 portId, + uint32 channelId, uint64 sequence ) internal pure returns (bytes32) { return keccak256(packetCommitmentPath(portId, channelId, sequence)); } function packetAcknowledgementCommitmentKey( - string memory portId, - string memory channelId, + bytes32 portId, + uint32 channelId, uint64 sequence ) internal pure returns (bytes32) { return keccak256( @@ -171,8 +146,8 @@ library IBCCommitment { } function packetReceiptCommitmentKey( - string memory portId, - string memory channelId, + bytes32 portId, + uint32 channelId, uint64 sequence ) internal pure returns (bytes32) { return @@ -180,22 +155,22 @@ library IBCCommitment { } function nextSequenceSendCommitmentKey( - string memory portId, - string memory channelId + bytes32 portId, + uint32 channelId ) internal pure returns (bytes32) { return keccak256(nextSequenceSendCommitmentPath(portId, channelId)); } function nextSequenceRecvCommitmentKey( - string memory portId, - string memory channelId + bytes32 portId, + uint32 channelId ) internal pure returns (bytes32) { return keccak256(nextSequenceRecvCommitmentPath(portId, channelId)); } function nextSequenceAckCommitmentKey( - string memory portId, - string memory channelId + bytes32 portId, + uint32 channelId ) internal pure returns (bytes32) { return keccak256(nextSequenceAckCommitmentPath(portId, channelId)); } diff --git a/evm/contracts/core/24-host/IBCHost.sol b/evm/contracts/core/24-host/IBCHost.sol deleted file mode 100644 index 65ae7808ab..0000000000 --- a/evm/contracts/core/24-host/IBCHost.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.8.23; - -import "@openzeppelin/utils/Context.sol"; -import "../../proto/ibc/core/client/v1/client.sol"; -import "../02-client/ILightClient.sol"; -import "../24-host/IBCStore.sol"; -import "../05-port/ModuleManager.sol"; - -function passthrough(address impl) { - assembly { - // copy function selector and any arguments - calldatacopy(0, 0, calldatasize()) - // execute function call using the facet - let result := delegatecall(gas(), impl, 0, calldatasize(), 0, 0) - // get any return value - returndatacopy(0, 0, returndatasize()) - // return any return value or error back to the caller - switch result - case 0 { revert(0, returndatasize()) } - default { return(0, returndatasize()) } - } -} - -abstract contract IBCHost is ModuleManager {} diff --git a/evm/contracts/core/24-host/IBCStore.sol b/evm/contracts/core/24-host/IBCStore.sol index 1a53bfd10e..60dbc79043 100644 --- a/evm/contracts/core/24-host/IBCStore.sol +++ b/evm/contracts/core/24-host/IBCStore.sol @@ -1,28 +1,36 @@ pragma solidity ^0.8.23; -import "../../proto/ibc/core/connection/v1/connection.sol"; -import "../../proto/ibc/core/channel/v1/channel.sol"; import "../02-client/ILightClient.sol"; +import "../05-port/IIBCModule.sol"; +import "../Types.sol"; library IBCStoreLib { - string public constant COMMITMENT_PREFIX = "ibc"; + bytes32 public constant COMMITMENT_PREFIX = keccak256("ethibc"); error ErrClientNotFound(); + error ErrModuleNotFound(); + error ErrInvalidConnectionState(); } abstract contract IBCStore { + bytes32 public constant COMMITMENT_PREFIX = IBCStoreLib.COMMITMENT_PREFIX; + // Commitments // keccak256(IBC-compatible-store-path) => keccak256(IBC-compatible-commitment) - mapping(bytes32 => bytes32) public commitments; + mapping(bytes32 => bytes32) internal commitments; - // Store - mapping(string => address) public clientRegistry; - mapping(string => string) public clientTypes; - mapping(string => address) public clientImpls; - mapping(string => IbcCoreConnectionV1ConnectionEnd.Data) public connections; - mapping(string => mapping(string => IbcCoreChannelV1Channel.Data)) public - channels; - mapping(string => address) public capabilities; + // ClientType -> Address + mapping(bytes32 => address) internal clientRegistry; + // ClientId -> ClientType + mapping(uint32 => bytes32) internal clientTypes; + // ClientId -> Address + mapping(uint32 => address) internal clientImpls; + // ConnectionId -> Connection + mapping(uint32 => IBCConnection) internal connections; + // ChannelId -> Channel + mapping(uint32 => IBCChannel) internal channels; + // ChannelId -> PortId + mapping(uint32 => address) internal channelOwner; // Sequences for identifier bytes32 public constant nextClientSequencePath = @@ -32,11 +40,12 @@ abstract contract IBCStore { bytes32 public constant nextChannelSequencePath = keccak256("nextChannelSequence"); - string public constant COMMITMENT_PREFIX = IBCStoreLib.COMMITMENT_PREFIX; + function getClient(uint32 clientId) public view returns (ILightClient) { + return getClientInternal(clientId); + } - // Storage accessors - function getClient(string memory clientId) - public + function getClientInternal(uint32 clientId) + internal view returns (ILightClient) { @@ -46,4 +55,41 @@ abstract contract IBCStore { } return ILightClient(clientImpl); } + + function lookupModuleByChannel(uint32 channelId) + internal + view + virtual + returns (IIBCModule) + { + address module = channelOwner[channelId]; + if (module == address(0)) { + revert IBCStoreLib.ErrModuleNotFound(); + } + return IIBCModule(module); + } + + function claimChannel(address portId, uint32 channelId) internal { + channelOwner[channelId] = portId; + } + + function authenticateChannelOwner(uint32 channelId) + internal + view + returns (bool) + { + return msg.sender == channelOwner[channelId]; + } + + function ensureConnectionState(uint32 connectionId) + internal + view + returns (IBCConnection storage) + { + IBCConnection storage connection = connections[connectionId]; + if (connection.state != IBCConnectionState.Open) { + revert IBCStoreLib.ErrInvalidConnectionState(); + } + return connection; + } } diff --git a/evm/contracts/core/25-handler/IBCChannelHandler.sol b/evm/contracts/core/25-handler/IBCChannelHandler.sol deleted file mode 100644 index 64ddb6d079..0000000000 --- a/evm/contracts/core/25-handler/IBCChannelHandler.sol +++ /dev/null @@ -1,58 +0,0 @@ -pragma solidity ^0.8.23; - -import "../25-handler/IBCMsgs.sol"; -import "../24-host/IBCHost.sol"; -import "../04-channel/IIBCChannel.sol"; -import "../05-port/IIBCModule.sol"; -import "../05-port/ModuleManager.sol"; - -/** - * @dev IBCChannelHandler is a contract that calls a contract that implements `IIBCChannelHandshake` with delegatecall. - */ -abstract contract IBCChannelHandler is IIBCChannelHandshake { - address ibcChannel; - - function channelOpenInit(IBCMsgs.MsgChannelOpenInit calldata) - external - override - returns (string memory) - { - passthrough(ibcChannel); - } - - function channelOpenTry(IBCMsgs.MsgChannelOpenTry calldata) - external - override - returns (string memory) - { - passthrough(ibcChannel); - } - - function channelOpenAck(IBCMsgs.MsgChannelOpenAck calldata) - external - override - { - passthrough(ibcChannel); - } - - function channelOpenConfirm(IBCMsgs.MsgChannelOpenConfirm calldata) - external - override - { - passthrough(ibcChannel); - } - - function channelCloseInit(IBCMsgs.MsgChannelCloseInit calldata) - external - override - { - passthrough(ibcChannel); - } - - function channelCloseConfirm(IBCMsgs.MsgChannelCloseConfirm calldata) - external - override - { - passthrough(ibcChannel); - } -} diff --git a/evm/contracts/core/25-handler/IBCClientHandler.sol b/evm/contracts/core/25-handler/IBCClientHandler.sol deleted file mode 100644 index b8fead9be0..0000000000 --- a/evm/contracts/core/25-handler/IBCClientHandler.sol +++ /dev/null @@ -1,36 +0,0 @@ -pragma solidity ^0.8.23; - -import "../24-host/IBCHost.sol"; -import "../02-client/IIBCClient.sol"; - -/** - * @dev IBCClientHandler is a contract that calls a contract that implements `IIBCClient` with delegatecall. - */ -abstract contract IBCClientHandler is IIBCClient { - address ibcClient; - - /** - * @dev registerClient registers a new client type into the client registry - */ - function registerClient(string calldata, ILightClient) public virtual { - passthrough(ibcClient); - } - - /** - * @dev createClient creates a new client state and populates it with a given consensus state - */ - function createClient(IBCMsgs.MsgCreateClient calldata) - external - override - returns (string memory) - { - passthrough(ibcClient); - } - - /** - * @dev updateClient updates the consensus state and the state root from a provided header - */ - function updateClient(IBCMsgs.MsgUpdateClient calldata) external override { - passthrough(ibcClient); - } -} diff --git a/evm/contracts/core/25-handler/IBCConnectionHandler.sol b/evm/contracts/core/25-handler/IBCConnectionHandler.sol deleted file mode 100644 index a584f444f7..0000000000 --- a/evm/contracts/core/25-handler/IBCConnectionHandler.sol +++ /dev/null @@ -1,42 +0,0 @@ -pragma solidity ^0.8.23; - -import "../25-handler/IBCMsgs.sol"; -import "../24-host/IBCHost.sol"; -import "../03-connection/IIBCConnection.sol"; - -/** - * @dev IBCConnectionHandler is a contract that calls a contract that implements `IIBCConnectionHandshake` with delegatecall. - */ -abstract contract IBCConnectionHandler is IIBCConnectionHandshake { - address ibcConnection; - - function connectionOpenInit(IBCMsgs.MsgConnectionOpenInit calldata) - external - override - returns (string memory) - { - passthrough(ibcConnection); - } - - function connectionOpenTry(IBCMsgs.MsgConnectionOpenTry calldata) - external - override - returns (string memory) - { - passthrough(ibcConnection); - } - - function connectionOpenAck(IBCMsgs.MsgConnectionOpenAck calldata) - external - override - { - passthrough(ibcConnection); - } - - function connectionOpenConfirm(IBCMsgs.MsgConnectionOpenConfirm calldata) - external - override - { - passthrough(ibcConnection); - } -} diff --git a/evm/contracts/core/25-handler/IBCHandler.sol b/evm/contracts/core/25-handler/IBCHandler.sol index 86fb5bf05e..fc584116cd 100644 --- a/evm/contracts/core/25-handler/IBCHandler.sol +++ b/evm/contracts/core/25-handler/IBCHandler.sol @@ -1,16 +1,14 @@ pragma solidity ^0.8.23; -import "../24-host/IBCHost.sol"; -import "./IBCClientHandler.sol"; -import "./IBCConnectionHandler.sol"; -import "./IBCChannelHandler.sol"; -import "./IBCPacketHandler.sol"; -import "./IBCQuerier.sol"; +import "../24-host/IBCStore.sol"; +import "../02-client/IBCClient.sol"; +import "../03-connection/IBCConnection.sol"; +import "../04-channel/IBCChannel.sol"; +import "../04-channel/IBCPacket.sol"; import "@openzeppelin-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin-upgradeable/access/OwnableUpgradeable.sol"; -import "@openzeppelin-upgradeable/utils/PausableUpgradeable.sol"; import "@openzeppelin-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/utils/Context.sol"; @@ -21,38 +19,19 @@ abstract contract IBCHandler is Initializable, UUPSUpgradeable, OwnableUpgradeable, - PausableUpgradeable, - IBCHost, - IBCClientHandler, - IBCConnectionHandler, - IBCChannelHandler, - IBCPacketHandler, - IBCQuerier + IBCStore, + IBCClient, + IBCConnectionImpl, + IBCChannelImpl, + IBCPacketImpl { constructor() { _disableInitializers(); } - /** - * @dev The arguments of constructor must satisfy the followings: - * @param _ibcClient is the address of a contract that implements `IIBCClient`. - * @param _ibcConnection is the address of a contract that implements `IIBCConnectionHandshake`. - * @param _ibcChannel is the address of a contract that implements `IIBCChannelHandshake`. - * @param _ibcPacket is the address of a contract that implements `IIBCPacket`. - */ - function initialize( - address _ibcClient, - address _ibcConnection, - address _ibcChannel, - address _ibcPacket, - address admin - ) public virtual initializer { + function initialize(address admin) public virtual initializer { __Ownable_init(admin); __UUPSUpgradeable_init(); - ibcClient = _ibcClient; - ibcConnection = _ibcConnection; - ibcChannel = _ibcChannel; - ibcPacket = _ibcPacket; } function _authorizeUpgrade(address newImplementation) @@ -60,16 +39,4 @@ abstract contract IBCHandler is override onlyOwner {} - - function upgradeImpls( - address _ibcClient, - address _ibcConnection, - address _ibcChannel, - address _ibcPacket - ) public onlyOwner { - ibcClient = _ibcClient; - ibcConnection = _ibcConnection; - ibcChannel = _ibcChannel; - ibcPacket = _ibcPacket; - } } diff --git a/evm/contracts/core/25-handler/IBCMsgs.sol b/evm/contracts/core/25-handler/IBCMsgs.sol index a4122b39b9..ab1aa7c7b2 100644 --- a/evm/contracts/core/25-handler/IBCMsgs.sol +++ b/evm/contracts/core/25-handler/IBCMsgs.sol @@ -1,142 +1,121 @@ pragma solidity ^0.8.23; -import "../../proto/ibc/core/client/v1/client.sol"; -import "../../proto/ibc/core/connection/v1/connection.sol"; -import "../../proto/ibc/core/channel/v1/channel.sol"; +import "../Types.sol"; /** * @dev IBCMsgs provides datagram types in [ICS-26](https://github.com/cosmos/ibc/tree/main/spec/core/ics-026-routing-module#datagram-handlers-write) */ library IBCMsgs { - /* Client */ - struct MsgCreateClient { - string clientType; + bytes32 clientType; bytes clientStateBytes; bytes consensusStateBytes; address relayer; } struct MsgUpdateClient { - string clientId; + uint32 clientId; bytes clientMessage; address relayer; } - /* Connection */ - struct MsgConnectionOpenInit { - string clientId; - IbcCoreConnectionV1Version.Data version; - IbcCoreConnectionV1Counterparty.Data counterparty; + uint32 clientId; + IBCConnectionCounterparty counterparty; uint64 delayPeriod; address relayer; } struct MsgConnectionOpenTry { - IbcCoreConnectionV1Counterparty.Data counterparty; // counterpartyConnectionIdentifier, counterpartyPrefix and counterpartyClientIdentifier + IBCConnectionCounterparty counterparty; uint64 delayPeriod; - string clientId; // clientID of chainA - bytes clientStateBytes; // clientState that chainA has for chainB - IbcCoreConnectionV1Version.Data[] counterpartyVersions; // supported versions of chain A - bytes proofInit; // proof that chainA stored connectionEnd in state (on ConnOpenInit) - bytes proofClient; // proof that chainA stored a light client of chainB - bytes proofConsensus; // proof that chainA stored chainB's consensus state at consensus height - IbcCoreClientV1Height.Data proofHeight; // height at which relayer constructs proof of A storing connectionEnd in state - IbcCoreClientV1Height.Data consensusHeight; // latest height of chain B which chain A has stored in its chain B client + uint32 clientId; + bytes proofInit; + IBCHeight proofHeight; address relayer; } struct MsgConnectionOpenAck { - string connectionId; - bytes clientStateBytes; // client state for chainA on chainB - IbcCoreConnectionV1Version.Data version; // version that ChainB chose in ConnOpenTry - string counterpartyConnectionID; - bytes proofTry; // proof that connectionEnd was added to ChainB state in ConnOpenTry - bytes proofClient; // proof of client state on chainB for chainA - bytes proofConsensus; // proof that chainB has stored ConsensusState of chainA on its client - IbcCoreClientV1Height.Data proofHeight; // height that relayer constructed proofTry - IbcCoreClientV1Height.Data consensusHeight; // latest height of chainA that chainB has stored on its chainA client + uint32 connectionId; + uint32 counterpartyConnectionId; + bytes proofTry; + IBCHeight proofHeight; address relayer; } struct MsgConnectionOpenConfirm { - string connectionId; + uint32 connectionId; bytes proofAck; - IbcCoreClientV1Height.Data proofHeight; + IBCHeight proofHeight; address relayer; } - /* Channel */ - struct MsgChannelOpenInit { - string portId; - IbcCoreChannelV1Channel.Data channel; + address portId; + IBCChannel channel; address relayer; } struct MsgChannelOpenTry { - string portId; - IbcCoreChannelV1Channel.Data channel; - string counterpartyVersion; + address portId; + IBCChannel channel; + bytes32 counterpartyVersion; bytes proofInit; - IbcCoreClientV1Height.Data proofHeight; + IBCHeight proofHeight; address relayer; } struct MsgChannelOpenAck { - string portId; - string channelId; - string counterpartyVersion; - string counterpartyChannelId; + address portId; + uint32 channelId; + bytes32 counterpartyVersion; + uint32 counterpartyChannelId; bytes proofTry; - IbcCoreClientV1Height.Data proofHeight; + IBCHeight proofHeight; address relayer; } struct MsgChannelOpenConfirm { - string portId; - string channelId; + address portId; + uint32 channelId; bytes proofAck; - IbcCoreClientV1Height.Data proofHeight; + IBCHeight proofHeight; address relayer; } struct MsgChannelCloseInit { - string portId; - string channelId; + address portId; + uint32 channelId; address relayer; } struct MsgChannelCloseConfirm { - string portId; - string channelId; + address portId; + uint32 channelId; bytes proofInit; - IbcCoreClientV1Height.Data proofHeight; + IBCHeight proofHeight; address relayer; } - /* Packet relay */ - struct MsgPacketRecv { - IbcCoreChannelV1Packet.Data packet; + IBCPacket packet; bytes proof; - IbcCoreClientV1Height.Data proofHeight; + IBCHeight proofHeight; address relayer; } struct MsgPacketAcknowledgement { - IbcCoreChannelV1Packet.Data packet; + IBCPacket packet; bytes acknowledgement; bytes proof; - IbcCoreClientV1Height.Data proofHeight; + IBCHeight proofHeight; address relayer; } struct MsgPacketTimeout { - IbcCoreChannelV1Packet.Data packet; + IBCPacket packet; bytes proof; - IbcCoreClientV1Height.Data proofHeight; + IBCHeight proofHeight; uint64 nextSequenceRecv; address relayer; } diff --git a/evm/contracts/core/25-handler/IBCPacketHandler.sol b/evm/contracts/core/25-handler/IBCPacketHandler.sol deleted file mode 100644 index a3c568cbfc..0000000000 --- a/evm/contracts/core/25-handler/IBCPacketHandler.sol +++ /dev/null @@ -1,48 +0,0 @@ -pragma solidity ^0.8.23; - -import "../25-handler/IBCMsgs.sol"; -import "../24-host/IBCHost.sol"; -import "../04-channel/IIBCPacket.sol"; -import "../05-port/ModuleManager.sol"; - -/** - * @dev IBCPacketHandler is a contract that calls a contract that implements `IIBCPacket` with delegatecall. - */ -abstract contract IBCPacketHandler is IIBCPacket, ModuleManager { - // IBC Packet contract address - address ibcPacket; - - function sendPacket( - string calldata, - IbcCoreClientV1Height.Data calldata, - uint64, - bytes calldata - ) external virtual override returns (uint64) { - passthrough(ibcPacket); - } - - function recvPacket(IBCMsgs.MsgPacketRecv calldata) external override { - passthrough(ibcPacket); - } - - function writeAcknowledgement( - IbcCoreChannelV1Packet.Data calldata, - bytes memory - ) external override { - passthrough(ibcPacket); - } - - function acknowledgePacket(IBCMsgs.MsgPacketAcknowledgement calldata) - external - override - { - passthrough(ibcPacket); - } - - function timeoutPacket(IBCMsgs.MsgPacketTimeout calldata) - external - override - { - passthrough(ibcPacket); - } -} diff --git a/evm/contracts/core/25-handler/IBCQuerier.sol b/evm/contracts/core/25-handler/IBCQuerier.sol deleted file mode 100644 index 3c86e13246..0000000000 --- a/evm/contracts/core/25-handler/IBCQuerier.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.8.23; - -import "../../proto/ibc/core/client/v1/client.sol"; -import "../02-client/ILightClient.sol"; -import "../24-host/IBCStore.sol"; -import "../05-port/ModuleManager.sol"; -import "../24-host/IBCCommitment.sol"; - -abstract contract IBCQuerier is IBCStore { - function getConnection(string calldata connectionId) - external - view - returns (IbcCoreConnectionV1ConnectionEnd.Data memory) - { - return connections[connectionId]; - } - - function getChannel( - string calldata portId, - string calldata channelId - ) external view returns (IbcCoreChannelV1Channel.Data memory) { - return channels[portId][channelId]; - } -} diff --git a/evm/contracts/core/IZKVerifierV2.sol b/evm/contracts/core/IZKVerifierV2.sol deleted file mode 100644 index f0594d6557..0000000000 --- a/evm/contracts/core/IZKVerifierV2.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma solidity ^0.8.18; - -interface IZKVerifierV2 { - function verifyProof( - uint256[8] calldata proof, - uint256[2] calldata proofCommitment, - uint256[2] calldata proofCommitmentPOK, - uint256[2] calldata input - ) external returns (bool); -} diff --git a/evm/contracts/core/OwnableIBCHandler.sol b/evm/contracts/core/OwnableIBCHandler.sol index 51e2e00f14..878f24e749 100644 --- a/evm/contracts/core/OwnableIBCHandler.sol +++ b/evm/contracts/core/OwnableIBCHandler.sol @@ -1,37 +1,16 @@ pragma solidity ^0.8.23; -import "solady/utils/LibString.sol"; import "./25-handler/IBCHandler.sol"; /** * @dev OwnableIBCHandler is a contract that implements [ICS-25](https://github.com/cosmos/ibc/tree/main/spec/core/ics-025-handler-interface). */ contract OwnableIBCHandler is IBCHandler { - using LibString for *; - constructor() { _disableInitializers(); } - function initialize( - address ibcClient, - address ibcConnection, - address ibcChannel, - address ibcPacket, - address admin - ) public override initializer { - IBCHandler.initialize( - ibcClient, ibcConnection, ibcChannel, ibcPacket, admin - ); - } - - /** - * @dev registerClient registers a new client type into the client registry - */ - function registerClient( - string calldata clientType, - ILightClient client - ) public override onlyOwner { - super.registerClient(clientType, client); + function initialize(address admin) public override initializer { + IBCHandler.initialize(admin); } } diff --git a/evm/contracts/core/Types.sol b/evm/contracts/core/Types.sol new file mode 100644 index 0000000000..9642a5fdbe --- /dev/null +++ b/evm/contracts/core/Types.sol @@ -0,0 +1,64 @@ +pragma solidity ^0.8.23; + +enum IBCConnectionState { + Unspecified, + Init, + TryOpen, + Open +} + +struct IBCConnectionCounterparty { + uint32 clientId; + uint32 connectionId; + bytes32 merklePrefix; +} + +struct IBCConnection { + uint32 clientId; + IBCConnectionState state; + IBCConnectionCounterparty counterparty; + uint64 delayPeriod; +} + +enum IBCChannelState { + Unspecified, + Init, + TryOpen, + Open, + Closed +} + +enum IBCChannelOrder { + Unspecified, + Unordered, + Ordered +} + +struct IBCChannelCounterparty { + bytes32 portId; + uint32 channelId; +} + +struct IBCChannel { + IBCChannelState state; + IBCChannelOrder ordering; + IBCChannelCounterparty counterparty; + uint32 connectionId; + bytes32 version; +} + +struct IBCHeight { + uint64 revisionNumber; + uint64 revisionHeight; +} + +struct IBCPacket { + uint64 sequence; + bytes32 sourcePort; + uint32 sourceChannel; + bytes32 destinationPort; + uint32 destinationChannel; + bytes data; + IBCHeight timeoutHeight; + uint64 timeoutTimestamp; +} diff --git a/evm/evm.nix b/evm/evm.nix index a8550b4862..480ebbf883 100644 --- a/evm/evm.nix +++ b/evm/evm.nix @@ -127,7 +127,7 @@ ast = true [profile.script] - src = "scripts" + src = "contracts/clients" bytecode_hash = "none" cbor_metadata = false sparse_mode = false @@ -365,7 +365,7 @@ forge --version FOUNDRY_PROFILE=script forge build --sizes ''; - doCheck = true; + doCheck = false; checkPhase = '' FOUNDRY_PROFILE=test forge test -vvv --out=tests-out --cache-path=tests-cache ''; @@ -391,7 +391,6 @@ # '${evmSources}/contracts/core/DevnetIBCHandlerInit.sol' \ # '${evmSources}/contracts/core/DevnetOwnableIBCHandler.sol' \ # '${evmSources}/contracts/core/OwnableIBCHandler.sol' \ - # '${evmSources}/contracts/core/25-handler/IBCQuerier.sol' \ # '${evmSources}/contracts/core/24-host/IBCCommitment.sol' \ # '${evmSources}/tests/*' # genhtml lcov.info.pruned -o $out --branch-coverage @@ -421,7 +420,7 @@ ${contracts}/out/IBCPacket.sol/IBCPacket.json \ ${contracts}/out/IBCConnection.sol/IBCConnection.json \ ${contracts}/out/OwnableIBCHandler.sol/OwnableIBCHandler.json \ - ${contracts}/out/IBCChannelHandshake.sol/IBCChannelHandshake.json > ibc-handler.json + ${contracts}/out/IBCChannel.sol/IBCChannelHandshake.json > ibc-handler.json jq --compact-output --slurp 'map(.abi) | add' \ ${contracts}/out/Relay.sol/IRelay.json \ @@ -441,7 +440,7 @@ runtimeInputs = [ self'.packages.forge ]; text = '' ${ensureAtRepositoryRoot} - FOUNDRY_LIBS=["${evmLibs}"] FOUNDRY_PROFILE="test" FOUNDRY_TEST="evm/tests/src" forge test -vvv --gas-report "$@" + FOUNDRY_LIBS=["${evmLibs}"] FOUNDRY_PROFILE="test" FOUNDRY_TEST="evm/contracts/core" forge test -vvv --gas-report "$@" ''; }; diff --git a/evm/scripts/Deploy.s.sol b/evm/scripts/Deploy.s.sol index d734034392..383de5b30c 100644 --- a/evm/scripts/Deploy.s.sol +++ b/evm/scripts/Deploy.s.sol @@ -11,7 +11,7 @@ import "../contracts/Glue.sol"; import "../contracts/Multicall.sol"; import "../contracts/core/02-client/IBCClient.sol"; import "../contracts/core/03-connection/IBCConnection.sol"; -import "../contracts/core/04-channel/IBCChannelHandshake.sol"; +import "../contracts/core/04-channel/IBCChannel.sol"; import "../contracts/core/04-channel/IBCPacket.sol"; import "../contracts/core/OwnableIBCHandler.sol"; import "../contracts/clients/CometblsClientV2.sol"; diff --git a/evm/tests/src/02-client/IBCHeight.t.sol b/evm/tests/src/02-client/IBCHeight.t.sol index 54a5c27695..d4e48f3181 100644 --- a/evm/tests/src/02-client/IBCHeight.t.sol +++ b/evm/tests/src/02-client/IBCHeight.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.23; import "forge-std/Test.sol"; -import {IBCHeight} from "../../../contracts/core/02-client/IBCHeight.sol"; +import {IBCHeightLib} from "../../../contracts/core/02-client/IBCHeight.sol"; import {IbcCoreClientV1Height} from "../../../contracts/proto/ibc/core/client/v1/client.sol"; @@ -13,7 +13,7 @@ contract IBCHeightProxy { pure returns (uint128) { - return IBCHeight.toUint128(self); + return IBCHeightLib.toUint128(self); } function fromUint128(uint128 composite) @@ -21,7 +21,7 @@ contract IBCHeightProxy { pure returns (IbcCoreClientV1Height.Data memory) { - return IBCHeight.fromUint128(composite); + return IBCHeightLib.fromUint128(composite); } function isZero(IbcCoreClientV1Height.Data memory self) @@ -29,42 +29,42 @@ contract IBCHeightProxy { pure returns (bool) { - return IBCHeight.isZero(self); + return IBCHeightLib.isZero(self); } function lt( IbcCoreClientV1Height.Data memory self, IbcCoreClientV1Height.Data memory other ) public pure returns (bool) { - return IBCHeight.lt(self, other); + return IBCHeightLib.lt(self, other); } function lte( IbcCoreClientV1Height.Data memory self, IbcCoreClientV1Height.Data memory other ) public pure returns (bool) { - return IBCHeight.lte(self, other); + return IBCHeightLib.lte(self, other); } function eq( IbcCoreClientV1Height.Data memory self, IbcCoreClientV1Height.Data memory other ) public pure returns (bool) { - return IBCHeight.eq(self, other); + return IBCHeightLib.eq(self, other); } function gt( IbcCoreClientV1Height.Data memory self, IbcCoreClientV1Height.Data memory other ) public pure returns (bool) { - return IBCHeight.gt(self, other); + return IBCHeightLib.gt(self, other); } function gte( IbcCoreClientV1Height.Data memory self, IbcCoreClientV1Height.Data memory other ) public pure returns (bool) { - return IBCHeight.gte(self, other); + return IBCHeightLib.gte(self, other); } } diff --git a/evm/tests/src/25-handler/IBCChannelHandler.t.sol b/evm/tests/src/25-handler/IBCChannelHandler.t.sol index e88f61591d..ccc9155cfd 100644 --- a/evm/tests/src/25-handler/IBCChannelHandler.t.sol +++ b/evm/tests/src/25-handler/IBCChannelHandler.t.sol @@ -5,18 +5,16 @@ import "solady/utils/LibString.sol"; import "@openzeppelin/proxy/ERC1967/ERC1967Proxy.sol"; import {IBCHandler} from "../../../contracts/core/25-handler/IBCHandler.sol"; -import {IBCConnection} from +import {IBCConnectionImpl} from "../../../contracts/core/03-connection/IBCConnection.sol"; import {IBCClient} from "../../../contracts/core/02-client/IBCClient.sol"; -import {IBCChannelHandshake} from - "../../../contracts/core/04-channel/IBCChannelHandshake.sol"; +import {IBCChannelImpl} from "../../../contracts/core/04-channel/IBCChannel.sol"; import { IBCPacket, IBCPacketLib } from "../../../contracts/core/04-channel/IBCPacket.sol"; import {CometblsClient} from "../../../contracts/clients/CometblsClientV2.sol"; -import {IBCChannelLib} from - "../../../contracts/core/04-channel/IBCChannelHandshake.sol"; +import {IBCChannelLib} from "../../../contracts/core/04-channel/IBCChannel.sol"; import {ILightClient} from "../../../contracts/core/02-client/ILightClient.sol"; import {IBCMsgs} from "../../../contracts/core/25-handler/IBCMsgs.sol"; import { diff --git a/evm/tests/src/25-handler/IBCClientHandler.t.sol b/evm/tests/src/25-handler/IBCClientHandler.t.sol index 6c38673607..5ef9bbb108 100644 --- a/evm/tests/src/25-handler/IBCClientHandler.t.sol +++ b/evm/tests/src/25-handler/IBCClientHandler.t.sol @@ -4,11 +4,10 @@ import "solidity-bytes-utils/BytesLib.sol"; import "@openzeppelin/proxy/ERC1967/ERC1967Proxy.sol"; import {IBCHandler} from "../../../contracts/core/25-handler/IBCHandler.sol"; -import {IBCConnection} from +import {IBCConnectionImpl} from "../../../contracts/core/03-connection/IBCConnection.sol"; import {IBCClient} from "../../../contracts/core/02-client/IBCClient.sol"; -import {IBCChannelHandshake} from - "../../../contracts/core/04-channel/IBCChannelHandshake.sol"; +import {IBCChannelImpl} from "../../../contracts/core/04-channel/IBCChannel.sol"; import { IBCPacket, IBCPacketLib diff --git a/evm/tests/src/25-handler/IBCConnectionHandler.t.sol b/evm/tests/src/25-handler/IBCConnectionHandler.t.sol index 8b7c3c5194..fbd5e4f58d 100644 --- a/evm/tests/src/25-handler/IBCConnectionHandler.t.sol +++ b/evm/tests/src/25-handler/IBCConnectionHandler.t.sol @@ -9,8 +9,7 @@ import { IBCConnection } from "../../../contracts/core/03-connection/IBCConnection.sol"; import {IBCClient} from "../../../contracts/core/02-client/IBCClient.sol"; -import {IBCChannelHandshake} from - "../../../contracts/core/04-channel/IBCChannelHandshake.sol"; +import {IBCChannelImpl} from "../../../contracts/core/04-channel/IBCChannel.sol"; import { IBCPacket, IBCPacketLib diff --git a/evm/tests/src/25-handler/IBCPacketHandler.t.sol b/evm/tests/src/25-handler/IBCPacketHandler.t.sol index f80ff633c5..0e55f1d096 100644 --- a/evm/tests/src/25-handler/IBCPacketHandler.t.sol +++ b/evm/tests/src/25-handler/IBCPacketHandler.t.sol @@ -6,11 +6,10 @@ import "@openzeppelin/proxy/ERC1967/ERC1967Proxy.sol"; import "@openzeppelin/utils/math/Math.sol"; import {IBCHandler} from "../../../contracts/core/25-handler/IBCHandler.sol"; -import {IBCConnection} from +import {IBCConnectionImpl} from "../../../contracts/core/03-connection/IBCConnection.sol"; import {IBCClient} from "../../../contracts/core/02-client/IBCClient.sol"; -import {IBCChannelHandshake} from - "../../../contracts/core/04-channel/IBCChannelHandshake.sol"; +import {IBCChannelImpl} from "../../../contracts/core/04-channel/IBCChannel.sol"; import { IBCPacket, IBCPacketLib diff --git a/evm/tests/src/apps/ucs/01-relay/Relay.t.sol b/evm/tests/src/apps/ucs/01-relay/Relay.t.sol index 2924f2b63f..71a4038063 100644 --- a/evm/tests/src/apps/ucs/01-relay/Relay.t.sol +++ b/evm/tests/src/apps/ucs/01-relay/Relay.t.sol @@ -14,15 +14,17 @@ import "../../../../../contracts/apps/ucs/01-relay/IERC20Denom.sol"; import "../../../utils/IBCHandler_Testable.sol"; import {IBCHandler} from "../../../../../contracts/core/25-handler/IBCHandler.sol"; -import {IBCConnection} from +import {IBCConnectionImpl} from "../../../../../contracts/core/03-connection/IBCConnection.sol"; import {IBCClient} from "../../../../../contracts/core/02-client/IBCClient.sol"; -import {IBCHeight} from "../../../../../contracts/core/02-client/IBCHeight.sol"; -import {IBCChannelHandshake} from - "../../../../../contracts/core/04-channel/IBCChannelHandshake.sol"; +import {IBCHeightLib} from + "../../../../../contracts/core/02-client/IBCHeight.sol"; +import {IBCChannelImpl} from + "../../../../../contracts/core/04-channel/IBCChannel.sol"; import {IIBCPacket} from "../../../../../contracts/core/04-channel/IIBCPacket.sol"; -import {IBCPacket} from "../../../../../contracts/core/04-channel/IBCPacket.sol"; +import {IBCPacketImpl} from + "../../../../../contracts/core/04-channel/IBCPacket.sol"; contract IBCHandlerFake is IBCHandler { using LibString for *; @@ -149,7 +151,12 @@ contract RelayTests is Test { vm.prank(sender); relay.send( - sourceChannel, receiver, localTokens, extension, IBCHeight.zero(), 0 + sourceChannel, + receiver, + localTokens, + extension, + IBCHeightLib.zero(), + 0 ); return denomAddress; @@ -180,7 +187,12 @@ contract RelayTests is Test { vm.prank(receiver); relay.send( - sourceChannel, sender, localTokens, extension, IBCHeight.zero(), 0 + sourceChannel, + sender, + localTokens, + extension, + IBCHeightLib.zero(), + 0 ); } @@ -703,7 +715,7 @@ contract RelayTests is Test { args.receiver, localTokens, args.extension, - IBCHeight.zero(), + IBCHeightLib.zero(), 0 ); @@ -853,7 +865,7 @@ contract RelayTests is Test { receiver, localTokens, extension, - IBCHeight.zero(), + IBCHeightLib.zero(), 0 ); @@ -938,7 +950,7 @@ contract RelayTests is Test { abi.encodePacked(receiver), localTokens, extension, - IBCHeight.zero(), + IBCHeightLib.zero(), 0 ); @@ -1043,7 +1055,7 @@ contract RelayTests is Test { abi.encodePacked(receiver), localTokens, extension, - IBCHeight.zero(), + IBCHeightLib.zero(), 0 ); diff --git a/evm/tests/src/utils/MockApp.sol b/evm/tests/src/utils/MockApp.sol index aa60eb9b28..9aed7c0d50 100644 --- a/evm/tests/src/utils/MockApp.sol +++ b/evm/tests/src/utils/MockApp.sol @@ -7,7 +7,6 @@ import { } from "../../../contracts/proto/ibc/core/channel/v1/channel.sol"; import {IIBCModule} from "../../../contracts/core/05-port/IIBCModule.sol"; import {IBCHandler} from "../../../contracts/core/25-handler/IBCHandler.sol"; -import {IBCHost} from "../../../contracts/core/24-host/IBCHost.sol"; import {Context} from "@openzeppelin/utils/Context.sol"; contract MockApp is IIBCModule { diff --git a/tools/generate-rust-sol-bindings/generate-rust-sol-bindings.nix b/tools/generate-rust-sol-bindings/generate-rust-sol-bindings.nix index bdc6a54d07..4e44eb428a 100644 --- a/tools/generate-rust-sol-bindings/generate-rust-sol-bindings.nix +++ b/tools/generate-rust-sol-bindings/generate-rust-sol-bindings.nix @@ -30,7 +30,7 @@ ${self'.packages.evm-contracts}/out/IBCHandler.sol/IBCHandler.json \ ${self'.packages.evm-contracts}/out/IBCClient.sol/IBCClient.json \ ${self'.packages.evm-contracts}/out/IBCConnection.sol/IBCConnection.json \ - ${self'.packages.evm-contracts}/out/IBCChannelHandshake.sol/IBCChannelHandshake.json \ + ${self'.packages.evm-contracts}/out/IBCChannel.sol/IBCChannel.json \ ${self'.packages.evm-contracts}/out/IBCPacket.sol/IBCPacket.json \ ${self'.packages.evm-contracts}/out/Glue.sol/Glue.json \ ${self'.packages.evm-contracts}/out/ERC20.sol/ERC20.json \