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

Deliver messages directly to Polymer Dispatcher #31

Merged
merged 9 commits into from
Apr 20, 2024
Merged
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
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.
alfredo-stonk marked this conversation as resolved.
Show resolved Hide resolved
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
Loading