Skip to content

Commit

Permalink
Merge pull request #31 from catalystdao/polymer-ibc
Browse files Browse the repository at this point in the history
Deliver messages directly to Polymer Dispatcher
  • Loading branch information
reednaa authored Apr 20, 2024
2 parents e410087 + ec9e943 commit 681fc11
Show file tree
Hide file tree
Showing 6 changed files with 301 additions and 82 deletions.
2 changes: 1 addition & 1 deletion lib/vibc-core-smart-contracts
Submodule vibc-core-smart-contracts updated 47 files
+5 −2 .github/workflows/foundry.yml
+29 −0 .github/workflows/lint.yml
+3 −0 .gitmodules
+0 −4 .prettierignore
+0 −4 .prettierrc.yml
+23 −0 .solhint.json
+33 −49 contracts/base/GeneralMiddleware.sol
+357 −327 contracts/core/Dispatcher.sol
+36 −40 contracts/core/OpLightClient.sol
+47 −52 contracts/core/OpProofVerifier.sol
+96 −67 contracts/core/UniversalChannelHandler.sol
+23 −28 contracts/examples/Earth.sol
+164 −65 contracts/examples/Mars.sol
+102 −0 contracts/interfaces/IDispatcher.sol
+32 −18 contracts/interfaces/IbcDispatcher.sol
+47 −39 contracts/interfaces/IbcMiddleware.sol
+40 −28 contracts/interfaces/IbcReceiver.sol
+9 −10 contracts/interfaces/LightClient.sol
+14 −6 contracts/interfaces/ProofVerifier.sol
+215 −105 contracts/libs/Ibc.sol
+0 −40 contracts/utils/DummyConsensusStateManager.sol
+47 −0 contracts/utils/DummyLightClient.sol
+1 −1 contracts/utils/DummyProofVerifier.sol
+5 −11 contracts/utils/GasAudit.sol
+6 −2 foundry.toml
+1 −0 lib/openzeppelin-contracts-upgradeable
+13 −0 package.json
+1 −0 remappings.txt
+119 −0 script/Deploy.s.sol
+32 −0 script/README.md
+85 −50 test/Dispatcher.base.t.sol
+18 −22 test/Dispatcher.client.t.sol
+77 −66 test/Dispatcher.proof.t.sol
+373 −177 test/Dispatcher.t.sol
+53 −38 test/Ibc.t.sol
+18 −22 test/OpConsensusStateManager.t.sol
+14 −15 test/Proof.base.t.sol
+35 −0 test/TestUtils.t.sol
+59 −87 test/Verifier.t.sol
+107 −75 test/VirtualChain.sol
+19 −20 test/payload/ack.t.sol
+63 −65 test/universal.channel.t.sol
+168 −0 test/upgradeableProxy/Dispatcher.upgrade.t.sol
+66 −0 test/upgradeableProxy/DispatcherUUPS.accessControl.t.sol
+603 −0 test/upgradeableProxy/upgrades/DispatcherV2.sol
+22 −0 test/upgradeableProxy/upgrades/DispatcherV2Initializable.sol
+719 −0 yarn.lock
6 changes: 3 additions & 3 deletions script/Deploy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { BaseMultiChainDeployer} from "./BaseMultiChainDeployer.s.sol";
// Import all the Apps for deployment here.
import { IncentivizedMockEscrow } from "../src/apps/mock/IncentivizedMockEscrow.sol";
import { IncentivizedWormholeEscrow } from "../src/apps/wormhole/IncentivizedWormholeEscrow.sol";
import { IncentivizedPolymerEscrow } from "../src/apps/polymer/IncentivizedPolymerEscrow.sol";
import { UniversalPolymerEscrow } from "../src/apps/polymer/UniversalPolymerEscrow.sol";

contract DeployGeneralisedIncentives is BaseMultiChainDeployer {
using stdJson for string;
Expand Down Expand Up @@ -81,7 +81,7 @@ contract DeployGeneralisedIncentives is BaseMultiChainDeployer {

address expectedAddress = _getAddress(
abi.encodePacked(
type(IncentivizedPolymerEscrow).creationCode,
type(UniversalPolymerEscrow).creationCode,
abi.encode(vm.envAddress("SEND_LOST_GAS_TO"), polymerBridgeContract)
),
salt
Expand All @@ -90,7 +90,7 @@ contract DeployGeneralisedIncentives is BaseMultiChainDeployer {
// Check if it is already deployed. If it is, we skip.
if (expectedAddress.codehash != bytes32(0)) return expectedAddress;

IncentivizedPolymerEscrow polymerEscrow = new IncentivizedPolymerEscrow{salt: salt}(vm.envAddress("SEND_LOST_GAS_TO"), polymerBridgeContract);
UniversalPolymerEscrow polymerEscrow = new UniversalPolymerEscrow{salt: salt}(vm.envAddress("SEND_LOST_GAS_TO"), polymerBridgeContract);

incentive = address(polymerEscrow);
} else {
Expand Down
8 changes: 4 additions & 4 deletions script/bridge_contracts.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@
},
"Polymer": {
"basesepolia": {
"bridge": "0x50E32e236bfE4d514f786C9bC80061637dd5AF98",
"escrow": "0x147d414F1964c94c4Ac7422aC148aBddb4BEdC82"
"bridge": "0x9fcd52449261F732d017F8BD1CaCDc3dFbcD0361",
"escrow": "0x0000000000000000000010000000000000000000"
},
"optimismsepolia": {
"bridge": "0x34a0e37cCCEdaC70EC1807e5a1f6A4a91D4AE0Ce",
"escrow": "0x62e27C0bD89D7AC599Df8765cDEe0183A34A9929"
"bridge": "0xE2029629f51ab994210d671Dc08b7Ec94899b278",
"escrow": "0x0000000000000000000010000000000000000000"
}
}
}
79 changes: 79 additions & 0 deletions src/apps/polymer/APolymerEscrow.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {IncentivizedMessageEscrow} from "../../IncentivizedMessageEscrow.sol";
import "../../MessagePayload.sol";

/// @notice Scaffolding for Polymer Escrows
abstract contract APolymerEscrow is IncentivizedMessageEscrow {
error NonVerifiableMessage();
error NotImplemented();

struct VerifiedMessageHashContext {
bytes32 chainIdentifier;
bytes implementationIdentifier;
}

mapping(bytes32 => VerifiedMessageHashContext) public isVerifiedMessageHash;

constructor(address sendLostGasTo)
IncentivizedMessageEscrow(sendLostGasTo)
{}

function estimateAdditionalCost() external pure returns (address asset, uint256 amount) {
asset = address(0);
amount = 0;
}

function _uniqueSourceIdentifier() internal view override returns (bytes32 sourceIdentifier) {
return sourceIdentifier = bytes32(block.chainid);
}

function _proofValidPeriod(bytes32 /* destinationIdentifier */ ) internal pure override returns (uint64) {
return 0;
}

/** @dev Disable processPacket */
function processPacket(
bytes calldata, /* messagingProtocolContext */
bytes calldata, /* rawMessage */
bytes32 /* feeRecipitent */
) external payable override {
revert NotImplemented();
}

/** @dev Disable reemitAckMessage. Polymer manages the entire flow, so we don't need to worry about expired proofs. */
function reemitAckMessage(
bytes32 /* sourceIdentifier */,
bytes calldata /* implementationIdentifier */,
bytes calldata /* receiveAckWithContext */
) external payable override {
revert NotImplemented();
}

/** @dev Disable timeoutMessage */
function timeoutMessage(
bytes32 /* sourceIdentifier */,
bytes calldata /* implementationIdentifier */,
uint256 /* originBlockNumber */,
bytes calldata /* message */
) external payable override {
revert NotImplemented();
}

/// @notice This function is used to allow acks to be executed twice (if the first one ran out of gas)
/// This is not intended to allow processPacket to work.
function _verifyPacket(bytes calldata, /* messagingProtocolContext */ bytes calldata _message)
internal
view
override
returns (bytes32 sourceIdentifier, bytes memory implementationIdentifier, bytes calldata message_)
{
sourceIdentifier = isVerifiedMessageHash[keccak256(_message)].chainIdentifier;
implementationIdentifier = isVerifiedMessageHash[keccak256(_message)].implementationIdentifier;

if (sourceIdentifier == bytes32(0)) revert NonVerifiableMessage();

message_ = _message;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {IncentivizedMessageEscrow} from "../../IncentivizedMessageEscrow.sol";
import {APolymerEscrow} from "./APolymerEscrow.sol";
import "../../MessagePayload.sol";

import {AckPacket} from "vibc-core-smart-contracts/libs/Ibc.sol";
Expand All @@ -13,83 +13,14 @@ import {
} from "vibc-core-smart-contracts/interfaces/IbcMiddleware.sol";

/// @notice Polymer implementation of the Generalised Incentives based on vIBC.
contract IncentivizedPolymerEscrow is IncentivizedMessageEscrow, IbcMwUser, IbcUniversalPacketReceiver {
error NotEnoughGasProvidedForVerification();
error NonVerifiableMessage();
error NotImplemented();

struct VerifiedMessageHashContext {
bytes32 chainIdentifier;
bytes implementationIdentifier;
}

mapping(bytes32 => VerifiedMessageHashContext) public isVerifiedMessageHash;
// packet will timeout if it's delivered on the destination chain after (this block time + _TIMEOUT_AFTER_BLOCK).
uint64 constant _TIMEOUT_AFTER_BLOCK = 1 days;
contract UniversalPolymerEscrow is APolymerEscrow, IbcMwUser, IbcUniversalPacketReceiver {

constructor(address sendLostGasTo, address messagingProtocol)
IncentivizedMessageEscrow(sendLostGasTo)
APolymerEscrow(sendLostGasTo)
IbcMwUser(messagingProtocol)
{}

function estimateAdditionalCost() external pure returns (address asset, uint256 amount) {
asset = address(0);
amount = 0;
}

function _uniqueSourceIdentifier() internal view override returns (bytes32 sourceIdentifier) {
return sourceIdentifier = bytes32(block.chainid);
}

function _proofValidPeriod(bytes32 /* destinationIdentifier */ ) internal pure override returns (uint64) {
return 0;
}

/** @dev Disable processPacket */
function processPacket(
bytes calldata, /* messagingProtocolContext */
bytes calldata, /* rawMessage */
bytes32 /* feeRecipitent */
) external payable override {
revert NotImplemented();
}

/** @dev Disable reemitAckMessage. Polymer manages the entire flow, so we don't need to worry about expired proofs. */
function reemitAckMessage(
bytes32 /* sourceIdentifier */,
bytes calldata /* implementationIdentifier */,
bytes calldata /* receiveAckWithContext */
) external payable override {
revert NotImplemented();
}

/** @dev Disable timeoutMessage */
function timeoutMessage(
bytes32 /* sourceIdentifier */,
bytes calldata /* implementationIdentifier */,
uint256 /* originBlockNumber */,
bytes calldata /* message */
) external payable override {
revert NotImplemented();
}

/// @notice This function is used to allow acks to be executed twice (if the first one ran out of gas)
/// This is not intended to allow processPacket to work.
function _verifyPacket(bytes calldata, /* messagingProtocolContext */ bytes calldata _message)
internal
view
override
returns (bytes32 sourceIdentifier, bytes memory implementationIdentifier, bytes calldata message_)
{
sourceIdentifier = isVerifiedMessageHash[keccak256(_message)].chainIdentifier;
implementationIdentifier = isVerifiedMessageHash[keccak256(_message)].implementationIdentifier;

if (sourceIdentifier == bytes32(0)) revert NonVerifiableMessage();

message_ = _message;
}

// packet.srcPortAddr is the IncentivizedPolymerEscrow address on the source chain.
// packet.srcPortAddr is the UniversalPolymerEscrow address on the source chain.
// packet.destPortAddr is the address of this contract.
// channelId: the universal channel id from the running chain's perspective, which can be used to identify the counterparty chain.
function onRecvUniversalPacket(bytes32 channelId, UniversalPacket calldata packet)
Expand Down Expand Up @@ -145,7 +76,7 @@ contract IncentivizedPolymerEscrow is IncentivizedMessageEscrow, IbcMwUser, IbcU
* Each universal channel/channelId represents a directional path from the running chain to a destination chain.
* Universal ChannelIds should _destChainIdToChannelIdd from the Polymer registry.
* Although everyone is free to establish their own channels, they're not "officially" vetted until they're in the Polymer registry.
* @param destinationImplementation IncentivizedPolymerEscrow address on the counterparty chain.
* @param destinationImplementation UniversalPolymerEscrow address on the counterparty chain.
* @param message packet payload
* @param deadline Packet will timeout after the dest chain's block time in nanoseconds since the epoch passes timeoutTimestamp.
*/
Expand Down
Loading

0 comments on commit 681fc11

Please sign in to comment.