Skip to content

Commit

Permalink
Merge pull request #78 from open-ibc/thomas/add-ken-vibc-refactor
Browse files Browse the repository at this point in the history
update to vibc v2 with polymer regsitry refactor
  • Loading branch information
kenobijon authored Apr 20, 2024
2 parents eaefc30 + b50060c commit aafb21f
Show file tree
Hide file tree
Showing 17 changed files with 269 additions and 272 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ node_modules
# Hardhat files
/cache
/artifacts
/vibcArtifacts

# TypeChain files
/typechain
Expand Down
6 changes: 3 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "lib/polymer-registry-poc"]
path = lib/polymer-registry-poc
url = https://github.com/tmsdkeys/polymer-registry-poc
[submodule "lib/polymer-registry"]
path = lib/polymer-registry
url = https://github.com/polymerdao/polymer-registry
4 changes: 4 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ install:
echo "Installing dependencies"
npm install
forge install --shallow
echo "Dependencies installed"
echo "Building VIBC core smart contracts in lib..."
cd lib/vibc-core-smart-contracts && forge build --contracts ./contracts/core --out ../../vibcArtifacts && cd ../..
echo "VIBC core smart contracts built"

# Build config file at location specified in the .env file
# Usage: just build-config
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,21 @@ From the root directory run:
just install
```

to install the [vIBC core smart contracts](https://github.com/open-ibc/vibc-core-smart-contracts) as a dependency.
to install the [vIBC core smart contracts](https://github.com/open-ibc/vibc-core-smart-contracts) and the [Polymer registry](https://github.com/polymerdao/polymer-registry) as a dependency.

Additionally Hardhat will be installed as a dev dependency with some useful plugins. Check `package.json` for an exhaustive list.

> Note: In case you're experiencing issues with dependencies using the `just install` recipe, check that all prerequisites are correctly installed. If issues persist with forge, try to do the individual dependency installations...
### Version compatibility

| IBC-App-Solidity | vIBC core | Polymer Registry |
|-------------------|-----------|-----------|
| v0.1.0 | v1.0.0 | X |
| v0.2.0 | v1.0.0 | v0.1.0* |
| v1.0.0 | v2.0.0 | X |
| v1.1.0 | Yes | v0.0.1 |

## ⚙️ Set up your environment and configuration

The idea is to ensure that most configuration to add Polymer's vIBC is added as custom data in the configuration file of your development environment, e.g. Hardhat or Foundry. (Note that at the time of writing, only Hardhat is fully supported).
Expand Down
6 changes: 3 additions & 3 deletions config/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"isUniversal": true,
"deploy": {
"optimism": "",
"molten": ""
"base": ""
},
"createChannel": {
"srcChain": "",
Expand All @@ -20,7 +20,7 @@
"channelId": "channel-n",
"timeout": 36000
},
"molten": {
"base": {
"portAddr": "0x1234567890abcdef1234567890abcdef12345678",
"channelId": "channel-n",
"timeout": 36000
Expand All @@ -32,7 +32,7 @@
"channelId": "channel-n",
"timeout": 36000
},
"molten": {
"base": {
"portAddr": "0x1234567890abcdef1234567890abcdef12345678",
"channelId": "channel-n",
"timeout": 36000
Expand Down
12 changes: 8 additions & 4 deletions contracts/XCounter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import "./base/CustomChanIbcApp.sol";
contract XCounter is CustomChanIbcApp {
// app specific state
uint64 public counter;
mapping (uint64 => address) public counterMap;

mapping(uint64 => address) public counterMap;

constructor(IbcDispatcher _dispatcher) CustomChanIbcApp(_dispatcher) {}

Expand All @@ -28,7 +27,7 @@ contract XCounter is CustomChanIbcApp {
* @param channelId The ID of the channel (locally) to send the packet to.
* @param timeoutSeconds The timeout in seconds (relative).
*/
function sendPacket( bytes32 channelId, uint64 timeoutSeconds) external {
function sendPacket(bytes32 channelId, uint64 timeoutSeconds) external {
// incrementing counter on source chain
increment();

Expand All @@ -47,7 +46,12 @@ contract XCounter is CustomChanIbcApp {
* MUST be overriden by the inheriting contract.
* @param packet the IBC packet encoded by the source and relayed by the relayer.
*/
function onRecvPacket(IbcPacket memory packet) external override onlyIbcDispatcher returns (AckPacket memory ackPacket) {
function onRecvPacket(IbcPacket memory packet)
external
override
onlyIbcDispatcher
returns (AckPacket memory ackPacket)
{
recvedPackets.push(packet);
// decoding the caller address from the packet data
address _caller = abi.decode(packet.data, (address));
Expand Down
178 changes: 84 additions & 94 deletions contracts/base/CustomChanIbcApp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,27 @@

pragma solidity ^0.8.9;

import { IbcPacket, AckPacket, ChannelOrder, CounterParty, invalidCounterPartyPortId } from "@open-ibc/vibc-core-smart-contracts/contracts/libs/Ibc.sol";
import { IbcReceiverBase, IbcReceiver, IbcChannelReceiver } from "@open-ibc/vibc-core-smart-contracts/contracts/interfaces/IbcReceiver.sol";
import { IbcDispatcher } from "@open-ibc/vibc-core-smart-contracts/contracts/interfaces/IbcDispatcher.sol";
import { Ics23Proof } from "@open-ibc/vibc-core-smart-contracts/contracts/interfaces/ProofVerifier.sol";
import {
IbcPacket, AckPacket, ChannelOrder, IBCErrors
} from "@open-ibc/vibc-core-smart-contracts/contracts/libs/Ibc.sol";
import {IbcReceiverBase, IbcReceiver} from "@open-ibc/vibc-core-smart-contracts/contracts/interfaces/IbcReceiver.sol";
import {IbcDispatcher} from "@open-ibc/vibc-core-smart-contracts/contracts/interfaces/IbcDispatcher.sol";

// CustomChanIbcApp is a contract that can be used as a base contract
// for IBC-enabled contracts that send packets over a custom IBC channel.
contract CustomChanIbcApp is IbcReceiverBase, IbcReceiver {
struct ChannelMapping {
bytes32 channelId;
bytes32 cpChannelId;
}
}

// received packet as chain B
IbcPacket[] public recvedPackets;
// received ack packet as chain A
AckPacket[] public ackPackets;
// received timeout packet as chain A
IbcPacket[] public timeoutPackets;

// ChannelMapping array with the channel IDs of the connected channels
ChannelMapping[] public connectedChannels;

Expand All @@ -42,7 +43,7 @@ contract CustomChanIbcApp is IbcReceiverBase, IbcReceiver {
return connectedChannels;
}

/**
/**
* @dev Implement a function to send a packet that calls the dispatcher.sendPacket function
* It has the following function handle:
* function sendPacket(bytes32 channelId, bytes calldata payload, uint64 timeoutTimestamp) external;
Expand All @@ -51,23 +52,33 @@ contract CustomChanIbcApp is IbcReceiverBase, IbcReceiver {
/**
* @dev Packet lifecycle callback that implements packet receipt logic and returns and acknowledgement packet.
* MUST be overriden by the inheriting contract.
*
* @param packet the IBC packet encoded by the source and relayed by the relayer.
*/
function onRecvPacket(IbcPacket memory packet) external virtual onlyIbcDispatcher returns (AckPacket memory ackPacket) {
function onRecvPacket(IbcPacket memory packet)
external
virtual
onlyIbcDispatcher
returns (AckPacket memory ackPacket)
{
recvedPackets.push(packet);
// do logic

// solhint-disable-next-line quotes
return AckPacket(true, abi.encodePacked("{ 'account': 'account', 'reply': 'got the message' }"));
}

/**
* @dev Packet lifecycle callback that implements packet acknowledgment logic.
* MUST be overriden by the inheriting contract.
*
*
* @param packet the IBC packet encoded by the source and relayed by the relayer.
* @param ack the acknowledgment packet encoded by the destination and relayed by the relayer.
*/
function onAcknowledgementPacket(IbcPacket calldata packet, AckPacket calldata ack) external virtual onlyIbcDispatcher {
function onAcknowledgementPacket(IbcPacket calldata packet, AckPacket calldata ack)
external
virtual
onlyIbcDispatcher
{
ackPackets.push(ack);
// do logic
}
Expand All @@ -76,7 +87,6 @@ contract CustomChanIbcApp is IbcReceiverBase, IbcReceiver {
* @dev Packet lifecycle callback that implements packet receipt logic and return and acknowledgement packet.
* MUST be overriden by the inheriting contract.
* NOT SUPPORTED YET
*
* @param packet the IBC packet encoded by the counterparty and relayed by the relayer
*/
function onTimeoutPacket(IbcPacket calldata packet) external virtual onlyIbcDispatcher {
Expand All @@ -86,113 +96,93 @@ contract CustomChanIbcApp is IbcReceiverBase, IbcReceiver {

/**
* @dev Create a custom channel between two IbcReceiver contracts
* @param local a CounterParty struct with the local chain's portId and version (channelId can be empty)
* @param version a version string to negotiate between the two chains
* @param ordering the channel ordering (NONE, UNORDERED, ORDERED) equivalent to (0, 1, 2)
* @param feeEnabled in production, you'll want to enable this to avoid spamming create channel calls (costly for relayers)
* @param connectionHops 2 connection hops to connect to the destination via Polymer
* @param counterparty the address of the destination chain contract you want to connect to
* @param proof ICS23 proof struct with dummy data (only needed on ChanOpenTry)
* @param counterpartyPortId the portID of the destination chain contract you want to connect to
*/
function createChannel(
CounterParty calldata local,
uint8 ordering,
bool feeEnabled,
string[] calldata connectionHops,
CounterParty calldata counterparty,
Ics23Proof calldata proof
) external virtual onlyOwner{

dispatcher.openIbcChannel(
IbcChannelReceiver(address(this)),
local,
ChannelOrder(ordering),
feeEnabled,
connectionHops,
counterparty,
proof
);
}

function onOpenIbcChannel(
string calldata version,
ChannelOrder,
bool,
string[] calldata,
CounterParty calldata counterparty
) external view virtual onlyIbcDispatcher returns (string memory selectedVersion) {
if (bytes(counterparty.portId).length <= 8) {
revert invalidCounterPartyPortId();
}
/**
* Version selection is determined by if the callback is invoked on behalf of ChanOpenInit or ChanOpenTry.
* ChanOpenInit: self version should be provided whereas the counterparty version is empty.
* ChanOpenTry: counterparty version should be provided whereas the self version is empty.
* In both cases, the selected version should be in the supported versions list.
*/
bool foundVersion = false;
selectedVersion = keccak256(abi.encodePacked(version)) == keccak256(abi.encodePacked(""))
? counterparty.version
: version;
for (uint256 i = 0; i < supportedVersions.length; i++) {
if (keccak256(abi.encodePacked(selectedVersion)) == keccak256(abi.encodePacked(supportedVersions[i]))) {
foundVersion = true;
break;
}
}
require(foundVersion, "Unsupported version");
// if counterpartyVersion is not empty, then it must be the same foundVersion
if (keccak256(abi.encodePacked(counterparty.version)) != keccak256(abi.encodePacked(""))) {
require(
keccak256(abi.encodePacked(counterparty.version)) == keccak256(abi.encodePacked(selectedVersion)),
"Version mismatch"
);
}

// do logic
uint8 ordering,
bool feeEnabled,
string[] calldata connectionHops,
string calldata counterpartyPortId
) external onlyOwner {
dispatcher.channelOpenInit(version, ChannelOrder(ordering), feeEnabled, connectionHops, counterpartyPortId);
}

return selectedVersion;
function onChanOpenInit(ChannelOrder, string[] calldata, string calldata, string calldata version)
external
view
virtual
onlyIbcDispatcher
returns (string memory selectedVersion)
{
return _openChannel(version);
}

function onConnectIbcChannel(
// solhint-disable-next-line ordering
function onChanOpenTry(
ChannelOrder,
string[] memory,
bytes32 channelId,
string memory,
bytes32 counterpartyChannelId,
string calldata counterpartyVersion
) external virtual onlyIbcDispatcher {
// ensure negotiated version is supported
bool foundVersion = false;
for (uint256 i = 0; i < supportedVersions.length; i++) {
if (keccak256(abi.encodePacked(counterpartyVersion)) == keccak256(abi.encodePacked(supportedVersions[i]))) {
foundVersion = true;
break;
}
}
require(foundVersion, "Unsupported version");
) external virtual onlyIbcDispatcher returns (string memory selectedVersion) {
return _connectChannel(channelId, counterpartyChannelId, counterpartyVersion);
}

// do logic
function onChanOpenAck(bytes32 channelId, bytes32 counterpartyChannelId, string calldata counterpartyVersion)
external
virtual
onlyIbcDispatcher
{
_connectChannel(channelId, counterpartyChannelId, counterpartyVersion);
}

ChannelMapping memory channelMapping = ChannelMapping({
channelId: channelId,
cpChannelId: counterpartyChannelId
});
connectedChannels.push(channelMapping);
function onChanOpenConfirm(bytes32 channelId) external virtual onlyIbcDispatcher {
// do logic
}

function onCloseIbcChannel(bytes32 channelId, string calldata, bytes32) external virtual onlyIbcDispatcher {
// logic to determin if the channel should be closed
bool channelFound = false;
for (uint256 i = 0; i < connectedChannels.length; i++) {
if (connectedChannels[i].channelId == channelId) {
for (uint256 j = i; j < connectedChannels.length - 1; j++) {
connectedChannels[j] = connectedChannels[j + 1];
}
connectedChannels.pop();
delete connectedChannels[i];
channelFound = true;
break;
}
}
require(channelFound, "Channel not found");
if (!channelFound) revert ChannelNotFound();
}

// do logic
function _connectChannel(bytes32 channelId, bytes32 counterpartyChannelId, string calldata counterpartyVersion)
private
returns (string memory version)
{
// ensure negotiated version is supported
for (uint256 i = 0; i < supportedVersions.length; i++) {
if (keccak256(abi.encodePacked(counterpartyVersion)) == keccak256(abi.encodePacked(supportedVersions[i]))) {
ChannelMapping memory channelMapping =
ChannelMapping({channelId: channelId, cpChannelId: counterpartyChannelId});
connectedChannels.push(channelMapping);

return counterpartyVersion;
}
}
revert UnsupportedVersion();
}

function _openChannel(string calldata version) private view returns (string memory selectedVersion) {
for (uint256 i = 0; i < supportedVersions.length; i++) {
if (keccak256(abi.encodePacked(version)) == keccak256(abi.encodePacked(supportedVersions[i]))) {
return version;
}
}
revert UnsupportedVersion();
}

/**
Expand Down
Loading

0 comments on commit aafb21f

Please sign in to comment.