Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: ics30 interfaces #215

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ $ make network-e2e

After launch the chains, execute the following command:

```
```sh
$ make e2e-test
```

Expand All @@ -80,7 +80,7 @@ To generate the proto encoders and decoders in solidity from proto files, you ne
Currently, [v0.1.0](https://github.com/datachainlab/solidity-protobuf/tree/v0.1.0) is required.

If you edit the proto definitions, you should execute the following command:
```
```sh
$ make SOLPB_DIR=/path/to/solidity-protobuf proto-sol
```

Expand Down
2 changes: 1 addition & 1 deletion contracts/apps/20-transfer/ICS20Transfer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity ^0.8.9;

import "../commons/IBCAppBase.sol";
import "../../core/05-port/IIBCModule.sol";
import "../../core/25-handler/IBCHandler.sol";
import "../../core/04-channel/IIBCChannel.sol";
import "../../proto/Channel.sol";
import "./ICS20Lib.sol";
import "solidity-bytes-utils/contracts/BytesLib.sol";
Expand Down
7 changes: 4 additions & 3 deletions contracts/apps/20-transfer/ICS20TransferBank.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import "solidity-bytes-utils/contracts/BytesLib.sol";
contract ICS20TransferBank is ICS20Transfer {
using BytesLib for bytes;

IBCHandler private immutable ibcHandler;
// either raw IBC Handler or middleware
IICS04Wrapper private immutable ibcHandler;
IICS20Bank private immutable bank;

constructor(IBCHandler ibcHandler_, IICS20Bank bank_) {
constructor(IICS04Wrapper ibcHandler_, IICS20Bank bank_) {
ibcHandler = ibcHandler_;
bank = bank_;
}
Expand Down Expand Up @@ -43,7 +44,7 @@ contract ICS20TransferBank is ICS20Transfer {
require(_burn(_msgSender(), denom, amount));
}
bytes memory packetData = ICS20Lib.marshalJSON(denom, amount, _encodeSender(_msgSender()), receiver);
IBCHandler(ibcAddress()).sendPacket(
IICS04Wrapper(ibcAddress()).sendPacket(
sourcePort, sourceChannel, Height.Data({revision_number: 0, revision_height: timeoutHeight}), 0, packetData
);
}
Expand Down
120 changes: 120 additions & 0 deletions contracts/apps/30-middleware/IICS30Middleware.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.9;

import "@openzeppelin/contracts/utils/Context.sol";
import "../../core/05-port/IIBCModule.sol";
import "../../core/04-channel/IIBCChannel.sol";
import "../commons/IBCAppBase.sol";

/**
* IBC host callbacacaks are delegated to underlying IBCAppBase module.
* IBCAppBase must be initialized with address of IIBCMiddleware as `ibcAddress`.
* IBCAppBase calls
*/
abstract contract IIBCMiddleware is Context, IBCAppBase, IICS04Wrapper {
// middleware has acccess to an underlying application which may be wrapped
// by more middleware.
IBCAppBase private ibcModule;

// middleware has access to ICS4Wrapper which may be core IBC Channel Handler
// or a higher-level middleware that wraps this middleware.
IICS04Wrapper private ics04Wrapper;

/// either raw IBC handler or other middleware
address private ibcHandler;

constructor(IBCAppBase ibcModule_, IICS04Wrapper ics04Wrapper_, address ibcHandler_) {
ibcModule = ibcModule_;
ics04Wrapper = ics04Wrapper_;
ibcHandler = ibcHandler_;
}

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

modifier onlyWrapped() {
require(
_msgSender() == address(ibcModule) || _msgSender() == address(this),
"IIBCMiddleware: caller is not the IBCAppBase or IICS04Wrapper"
);
_;
}

function onChanOpenInit(
Channel.Order order,
string[] calldata connectionHops,
string calldata portId,
string calldata channelId,
ChannelCounterparty.Data calldata counterparty,
string calldata version
) external virtual override onlyIBC {
ibcModule.onChanOpenInit(order, connectionHops, portId, channelId, counterparty, version);
}

function onChanOpenTry(
Channel.Order order,
string[] calldata connectionHops,
string calldata portId,
string calldata channelId,
ChannelCounterparty.Data calldata counterparty,
string calldata version,
string calldata counterpartyVersion
) external virtual override onlyIBC {
ibcModule.onChanOpenTry(order, connectionHops, portId, channelId, counterparty, version, counterpartyVersion);
}

function onChanOpenConfirm(string calldata portId, string calldata channelId) external virtual override onlyIBC {
ibcModule.onChanOpenConfirm(portId, channelId);
}

function onChanCloseInit(string calldata portId, string calldata channelId) external virtual override onlyIBC {
ibcModule.onChanCloseInit(portId, channelId);
}

function onChanCloseConfirm(string calldata portId, string calldata channelId) external virtual override onlyIBC {
ibcModule.onChanCloseConfirm(portId, channelId);
}

function onRecvPacket(Packet.Data calldata packet, address relayer)
external
virtual
override
onlyIBC
returns (bytes memory acknowledgement)
{
return ibcModule.onRecvPacket(packet, relayer);
}

function onAcknowledgementPacket(Packet.Data calldata packet, bytes calldata acknowledgement, address relayer)
external
virtual
override
onlyIBC
{
return ibcModule.onAcknowledgementPacket(packet, acknowledgement, relayer);
}

function onTimeoutPacket(Packet.Data calldata packet, address relayer) external virtual override onlyIBC {
return ibcModule.onTimeoutPacket(packet, relayer);
}

function writeAcknowledgement(
string calldata destinationPortId,
string calldata destinationChannel,
uint64 sequence,
bytes calldata acknowledgement
) external virtual override onlyWrapped {
ics04Wrapper.writeAcknowledgement(destinationPortId, destinationChannel, sequence, acknowledgement);
}

function sendPacket(
string calldata sourcePort,
string calldata sourceChannel,
Height.Data calldata timeoutHeight,
uint64 timeoutTimestamp,
bytes calldata data
) external virtual override onlyWrapped returns (uint64) {
return ics04Wrapper.sendPacket(sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data);
}
}
26 changes: 14 additions & 12 deletions contracts/core/04-channel/IIBCChannel.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,18 @@ interface IIBCChannelHandshake {
function channelCloseConfirm(IBCMsgs.MsgChannelCloseConfirm calldata msg_) external;
}

interface IIBCPacket {
interface IICS04Wrapper {
/**
* @dev writeAcknowledgement writes the packet execution acknowledgement to the state,
* which will be verified by the counterparty chain using AcknowledgePacket.
*/
function writeAcknowledgement(
string calldata destinationPortId,
string calldata destinationChannel,
uint64 sequence,
bytes calldata acknowledgement
) external;

/**
* @dev sendPacket is called by a module in order to send an IBC packet on a channel.
* The packet sequence generated for the packet to be sent is returned. An error
Expand All @@ -49,24 +60,15 @@ interface IIBCPacket {
uint64 timeoutTimestamp,
bytes calldata data
) external returns (uint64);
}

interface IIBCPacket is IICS04Wrapper {
/**
* @dev recvPacket is called by a module in order to receive & process an IBC packet
* sent on the corresponding channel end on the counterparty chain.
*/
function recvPacket(IBCMsgs.MsgPacketRecv calldata msg_) external;

/**
* @dev writeAcknowledgement writes the packet execution acknowledgement to the state,
* which will be verified by the counterparty chain using AcknowledgePacket.
*/
function writeAcknowledgement(
string calldata destinationPortId,
string calldata destinationChannel,
uint64 sequence,
bytes calldata acknowledgement
) external;

/**
* @dev AcknowledgePacket is called by a module to process the acknowledgement of a
* packet previously sent by the calling module on a channel to a counterparty
Expand Down
14 changes: 8 additions & 6 deletions contracts/core/25-handler/IBCPacketHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import "../05-port/IIBCModule.sol";
/**
* @dev IBCPacketHandler is a contract that calls a contract that implements `IIBCPacket` with delegatecall.
*/
abstract contract IBCPacketHandler is Context, ModuleManager {
abstract contract IBCPacketHandler is IICS04Wrapper, Context, ModuleManager {
using Address for address;

// IBC Packet contract address
Expand Down Expand Up @@ -45,14 +45,16 @@ abstract contract IBCPacketHandler is Context, ModuleManager {
Height.Data calldata timeoutHeight,
uint64 timeoutTimestamp,
bytes calldata data
) external {
) external returns (uint64) {
require(authenticateCapability(channelCapabilityPath(sourcePort, sourceChannel)));
bytes memory res = ibcPacket.functionDelegateCall(
abi.encodeWithSelector(
IIBCPacket.sendPacket.selector, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data
IICS04Wrapper.sendPacket.selector, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data
)
);
emit SendPacket(abi.decode(res, (uint64)), sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data);
uint64 sequence = abi.decode(res, (uint64));
emit SendPacket(sequence, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data);
return sequence;
}

function recvPacket(IBCMsgs.MsgPacketRecv calldata msg_) external {
Expand All @@ -62,7 +64,7 @@ abstract contract IBCPacketHandler is Context, ModuleManager {
if (acknowledgement.length > 0) {
ibcPacket.functionDelegateCall(
abi.encodeWithSelector(
IIBCPacket.writeAcknowledgement.selector,
IICS04Wrapper.writeAcknowledgement.selector,
msg_.packet.destination_port,
msg_.packet.destination_channel,
msg_.packet.sequence,
Expand All @@ -85,7 +87,7 @@ abstract contract IBCPacketHandler is Context, ModuleManager {
require(authenticateCapability(channelCapabilityPath(destinationPortId, destinationChannel)));
ibcPacket.functionDelegateCall(
abi.encodeWithSelector(
IIBCPacket.writeAcknowledgement.selector,
IICS04Wrapper.writeAcknowledgement.selector,
destinationPortId,
destinationChannel,
sequence,
Expand Down
Loading