Skip to content
Open
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
110 changes: 110 additions & 0 deletions solidity/contracts/hooks/PolygonZkevmHook.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.8.0;

/*@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@ HYPERLANE @@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@*/

// ============ Internal Imports ============
import {StandardHookMetadata} from "./libs/StandardHookMetadata.sol";
import {TypeCasts} from "../libs/TypeCasts.sol";
import {Message} from "../libs/Message.sol";
import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol";

// ============ External Imports ============
import {Address} from "@openzeppelin/contracts/utils/Address.sol";

import {IPolygonZkEVMBridge} from "../interfaces/polygonZkevm/IPolygonZkEVMBridge.sol";
import {MailboxClient} from "../client/MailboxClient.sol";

/**
* @title PolygonZkevmHook
* @notice Message hook to inform the {Polygon zkEVM chain Ism} of messages published through
* the native Polygon zkEVM bridge bridge.
*/
contract PolygonZkevmHook is IPostDispatchHook, MailboxClient {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you inherit from AbstractMessageIdAuthHook here, it'll mean less code duplication?

using StandardHookMetadata for bytes;
using Message for bytes;
using TypeCasts for bytes32;

// ============ Immutable Variables ============
IPolygonZkEVMBridge public immutable zkEvmBridge;

// left-padded address for ISM to verify messages
address public immutable ism;
// Domain of chain on which the ISM is deployed
uint32 public immutable destinationDomain;
// Polygon ZkevmBridge uses networkId 0 for Mainnet and 1 for rollup
uint32 public immutable zkEvmBridgeDestinationNetId;

constructor(
address _mailbox,
uint32 _destinationDomain,
address _ism,
address _zkEvmBridge,
uint32 _zkEvmBridgeDestinationNetId
) MailboxClient(_mailbox) {
require(
Address.isContract(_zkEvmBridge),
"PolygonzkEVMHook: invalid PolygonZkEVMBridge contract"
);
require(
_destinationDomain != 0,
"PolygonzkEVMHook: invalid destination domain"
);
require(
_zkEvmBridgeDestinationNetId <= 1,
"PolygonZkevmIsm: invalid ZkEVMBridge destination network id"
);
ism = _ism;
destinationDomain = _destinationDomain;
zkEvmBridge = IPolygonZkEVMBridge(_zkEvmBridge);
zkEvmBridgeDestinationNetId = uint8(_zkEvmBridgeDestinationNetId);
}

/// @inheritdoc IPostDispatchHook
function supportsMetadata(
bytes calldata
) public pure virtual override returns (bool) {
return true;
}

/// @dev This value is hardcoded to 0 because the Polygon zkEVM bridge does not support fee quotes
function quoteDispatch(
bytes calldata,
bytes calldata
) external pure override returns (uint256) {
return 0;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I imagine there's still some additional overhead for the relayer to submit the tx on the destination chain. You can follow using a childHook which is effectively an IGP:

metadata.msgValue(0) + childHook.quoteDispatch(metadata, message);

}

/// @inheritdoc IPostDispatchHook
function postDispatch(
bytes calldata metadata,
bytes calldata message
) external payable override {
require(
metadata.msgValue(0) < 2 ** 255,
"PolygonzkEVMHook: msgValue must be less than 2 ** 255"
);
bytes32 messageId = message.id();

zkEvmBridge.bridgeMessage{value: msg.value}(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only send the metadata.msgValue(0) and refund the rest

zkEvmBridgeDestinationNetId,
address(ism),
true,
abi.encode(messageId)
);
}

function hookType() external pure override returns (uint8) {
return uint8(IPostDispatchHook.Types.POLYGON_ZKEVM);
}
}
139 changes: 139 additions & 0 deletions solidity/contracts/hooks/PolygonZkevmV2Hook.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.8.0;

/*@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@ HYPERLANE @@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@*/

// ============ Internal Imports ============
import {StandardHookMetadata} from "./libs/StandardHookMetadata.sol";
import {TypeCasts} from "../libs/TypeCasts.sol";
import {Message} from "../libs/Message.sol";
import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol";
import {IInterchainGasPaymaster} from "../interfaces/IInterchainGasPaymaster.sol";

// ============ External Imports ============
import {Address} from "@openzeppelin/contracts/utils/Address.sol";

import {IPolygonZkEVMBridgeV2} from "../interfaces/polygonZkevm/IPolygonZkEVMBridgeV2.sol";
import {MailboxClient} from "../client/MailboxClient.sol";

/**
* @title PolygonzkEVMv2Hook
* @notice Message hook to inform the {Polygon zkEVM chain Ism} of messages published through
* the native Polygon zkEVM bridge bridge.
*/
contract PolygonZkevmV2Hook is IPostDispatchHook, MailboxClient {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inherit from AbstractMessageIdAuthHook here instead too

using StandardHookMetadata for bytes;
using Message for bytes;
using TypeCasts for bytes32;

uint256 private constant GAS_LIMIT = 150_000;
// ============ Immutable Variables ============
IPolygonZkEVMBridgeV2 public immutable zkEvmBridge;
IInterchainGasPaymaster public immutable interchainGasPaymaster;
// address for ISM to verify messages
// left-padded address for ISM to verify messages
address public immutable ism;
// Domain of chain on which the ISM is deployed
uint32 public immutable destinationDomain;
// Polygon ZkevmBridge uses networkId 0 for Mainnet and 1 for rollup
uint32 public immutable zkEvmBridgeDestinationNetId;

error InvalidContract(string Contract);
error InvalidInput(string input);

constructor(
address _mailbox,
uint32 _destinationDomain,
address _ism,
address _zkEvmBridge,
uint32 _zkEvmBridgeDestinationNetId,
address _interchainGasPaymaster
) MailboxClient(_mailbox) {
require(
Address.isContract(_zkEvmBridge),
"PolygonzkEVMv2Hook: invalid PolygonZkEVMBridge contract"
);
require(
_destinationDomain != 0,
"PolygonzkEVMv2Hook: invalid destination domain"
);
require(
_zkEvmBridgeDestinationNetId <= 1,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can only be 0 or 1 then?

"PolygonZkevmIsm: invalid ZkEVMBridge destination network id"
);
require(
Address.isContract(_interchainGasPaymaster),
"PolygonzkEVMv2Hook: invalid Interchain Gas Paymaster contract"
);
ism = _ism;
destinationDomain = _destinationDomain;
zkEvmBridge = IPolygonZkEVMBridgeV2(_zkEvmBridge);
zkEvmBridgeDestinationNetId = uint8(_zkEvmBridgeDestinationNetId);
interchainGasPaymaster = IInterchainGasPaymaster(
_interchainGasPaymaster
);
}

/// @inheritdoc IPostDispatchHook
function supportsMetadata(
bytes calldata
) public pure virtual override returns (bool) {
return true;
}

/// @dev This value is hardcoded to 0 because the Polygon zkEVM bridge does not support fee quotes
function quoteDispatch(
bytes calldata,
bytes calldata
) external view override returns (uint256) {
return
interchainGasPaymaster.quoteGasPayment(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make this child hook

destinationDomain,
GAS_LIMIT
);
}

/// @inheritdoc IPostDispatchHook
function postDispatch(
bytes calldata _metadata,
bytes calldata _message
) external payable override {
bytes32 messageId = keccak256(_message);
uint256 gasPayment = interchainGasPaymaster.quoteGasPayment(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

childHook.quoteDispatch()

destinationDomain,
150_000
);
require(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't need this require, igp will revert anyway

msg.value - _metadata.msgValue(0) >= gasPayment,
"PolygonzkEVMv2Hook: msgValue must be more than required gas"
);

interchainGasPaymaster.payForGas{value: gasPayment}(
messageId,
_metadata.destination(),
150_000,
msg.sender
);

zkEvmBridge.bridgeMessage{value: msg.value - gasPayment}(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

metadata.msgValue(0)

zkEvmBridgeDestinationNetId,
address(ism),
true,
abi.encode(messageId)
);
}

function hookType() external pure override returns (uint8) {
return uint8(IPostDispatchHook.Types.POLYGON_ZKEVM_V2);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ interface IInterchainSecurityModule {
ARB_L2_TO_L1,
WEIGHTED_MERKLE_ROOT_MULTISIG,
WEIGHTED_MESSAGE_ID_MULTISIG,
OP_L2_TO_L1
OP_L2_TO_L1,
POLYGON_ZKEVM,
POLYGON_ZKEVM_V2
}

/**
Expand Down
4 changes: 3 additions & 1 deletion solidity/contracts/interfaces/hooks/IPostDispatchHook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ interface IPostDispatchHook {
LAYER_ZERO_V1,
RATE_LIMITED,
ARB_L2_TO_L1,
OP_L2_TO_L1
OP_L2_TO_L1,
POLYGON_ZKEVM,
POLYGON_ZKEVM_V2
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: AGPL-3.0
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use forge submodules or npm for polygon dependencies, don't prefer to have dependencies vendored here


pragma solidity ^0.8.20;

interface IBasePolygonZkEVMGlobalExitRoot {
/**
* @dev Thrown when the caller is not the allowed contracts
*/
error OnlyAllowedContracts();

function updateExitRoot(bytes32 newRollupExitRoot) external;

function globalExitRootMap(
bytes32 globalExitRootNum
) external returns (uint256);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: AGPL-3.0

pragma solidity >=0.8.0;

/**
* @dev Define interface for PolygonZkEVM Bridge message receiver
*/
interface IBridgeMessageReceiver {
function onMessageReceived(
address originAddress,
uint32 originNetwork,
bytes memory data
) external payable;
}
Loading