add globalHookMetadata (#2743)

### Description

- Consolidating IGPMetadata and OPStackMetadata to versioned
GlobalHookMetadata
- Add `supportMetadata` to `IPostDispatchHook`

 - Metadata Schema
 [0:1] variant
 [2:33] msg.value
 [34:65] Gas limit for message (IGP)
 [66:85] Refund address for message (IGP)
 [86:] Custom metadata

### Drive-by changes

None

### Related issues

- fixes https://github.com/hyperlane-xyz/issues/issues/610


### Backward compatibility

No

### Testing

Unit tests

---------

Co-authored-by: Yorke Rhodes <yorke@hyperlane.xyz>
pull/2748/head
Kunal Arora 1 year ago committed by GitHub
parent 10765b7614
commit f783c4e96f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      solidity/contracts/GasRouter.sol
  2. 8
      solidity/contracts/Router.sol
  3. 21
      solidity/contracts/hooks/AbstractMessageIdAuthHook.sol
  4. 91
      solidity/contracts/hooks/AbstractPostDispatchHook.sol
  5. 47
      solidity/contracts/hooks/ConfigFallbackDomainRoutingHook.sol
  6. 11
      solidity/contracts/hooks/DefaultHook.sol
  7. 35
      solidity/contracts/hooks/DomainRoutingHook.sol
  8. 7
      solidity/contracts/hooks/ERC5164Hook.sol
  9. 36
      solidity/contracts/hooks/MerkleTreeHook.sol
  10. 13
      solidity/contracts/hooks/OPStackHook.sol
  11. 52
      solidity/contracts/hooks/PausableHook.sol
  12. 60
      solidity/contracts/hooks/StaticProtocolFee.sol
  13. 19
      solidity/contracts/hooks/aggregation/StaticAggregationHook.sol
  14. 13
      solidity/contracts/hooks/aggregation/StaticAggregationHookFactory.sol
  15. 59
      solidity/contracts/igps/InterchainGasPaymaster.sol
  16. 22
      solidity/contracts/interfaces/hooks/IPostDispatchHook.sol
  17. 164
      solidity/contracts/libs/hooks/GlobalHookMetadata.sol
  18. 78
      solidity/contracts/libs/hooks/IGPMetadata.sol
  19. 17
      solidity/contracts/libs/hooks/OPStackHookMetadata.sol
  20. 25
      solidity/contracts/test/TestPostDispatchHook.sol
  21. 41
      solidity/test/Mailbox.t.sol
  22. 28
      solidity/test/hooks/StaticProtocolFee.t.sol
  23. 16
      solidity/test/igps/InterchainGasPaymaster.t.sol
  24. 23
      solidity/test/isms/OPStackIsm.t.sol

@ -2,7 +2,7 @@
pragma solidity >=0.6.11;
import {Router} from "./Router.sol";
import {IGPMetadata} from "./libs/hooks/IGPMetadata.sol";
import {GlobalHookMetadata} from "./libs/hooks/GlobalHookMetadata.sol";
abstract contract GasRouter is Router {
// ============ Mutable Storage ============
@ -50,9 +50,11 @@ abstract contract GasRouter is Router {
_destinationDomain,
_mustHaveRemoteRouter(_destinationDomain),
"",
IGPMetadata.formatMetadata(
GlobalHookMetadata.formatMetadata(
0,
destinationGas[_destinationDomain],
address(this)
address(this),
bytes("")
)
);
}

@ -7,7 +7,7 @@ import {IInterchainGasPaymaster} from "./interfaces/IInterchainGasPaymaster.sol"
import {IMessageRecipient} from "./interfaces/IMessageRecipient.sol";
import {IMailbox} from "./interfaces/IMailbox.sol";
import {EnumerableMapExtended} from "./libs/EnumerableMapExtended.sol";
import {IGPMetadata} from "./libs/hooks/IGPMetadata.sol";
import {GlobalHookMetadata} from "./libs/hooks/GlobalHookMetadata.sol";
abstract contract Router is HyperlaneConnectionClient, IMessageRecipient {
using EnumerableMapExtended for EnumerableMapExtended.UintToBytes32Map;
@ -204,9 +204,11 @@ abstract contract Router is HyperlaneConnectionClient, IMessageRecipient {
) internal returns (bytes32 _messageId) {
// Ensure that destination chain has an enrolled router.
bytes32 _router = _mustHaveRemoteRouter(_destinationDomain);
bytes memory metadata = IGPMetadata.formatMetadata(
bytes memory metadata = GlobalHookMetadata.formatMetadata(
0,
_gasAmount,
_gasPaymentRefundAddress
_gasPaymentRefundAddress,
bytes("")
);
_messageId = mailbox.dispatch{value: _gasPayment}(
_destinationDomain,

@ -15,9 +15,10 @@ pragma solidity >=0.8.0;
// ============ Internal Imports ============
import {AbstractMessageIdAuthorizedIsm} from "../isms/hook/AbstractMessageIdAuthorizedIsm.sol";
import {AbstractPostDispatchHook} from "./AbstractPostDispatchHook.sol";
import {TypeCasts} from "../libs/TypeCasts.sol";
import {Message} from "../libs/Message.sol";
import {OPStackHookMetadata} from "../libs/hooks/OPStackHookMetadata.sol";
import {GlobalHookMetadata} from "../libs/hooks/GlobalHookMetadata.sol";
import {MailboxClient} from "../client/MailboxClient.sol";
import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol";
@ -28,9 +29,10 @@ import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol";
* @dev V3 WIP
*/
abstract contract AbstractMessageIdAuthHook is
IPostDispatchHook,
AbstractPostDispatchHook,
MailboxClient
{
using GlobalHookMetadata for bytes;
using Message for bytes;
// ============ Constants ============
@ -56,14 +58,11 @@ abstract contract AbstractMessageIdAuthHook is
destinationDomain = _destinationDomain;
}
/**
* @notice Hook to inform the optimism ISM of messages published through.
* metadata The metadata for the hook caller
* @param message The message being dispatched
*/
function postDispatch(bytes calldata metadata, bytes calldata message)
external
payable
// ============ Internal functions ============
/// @inheritdoc AbstractPostDispatchHook
function _postDispatch(bytes calldata metadata, bytes calldata message)
internal
override
{
bytes32 id = message.id();
@ -82,8 +81,6 @@ abstract contract AbstractMessageIdAuthHook is
_sendMessageId(metadata, payload);
}
// ============ Internal functions ============
/**
* @notice Send a message to the ISM.
* @param metadata The metadata for the hook caller

@ -0,0 +1,91 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.8.0;
/*@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@ HYPERLANE @@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@*/
// ============ Internal Imports ============
import {GlobalHookMetadata} from "../libs/hooks/GlobalHookMetadata.sol";
import {MailboxClient} from "../client/MailboxClient.sol";
import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol";
/**
* @title AbstractPostDispatch
* @notice Abstract post dispatch hook supporting the current global hook metadata variant.
*/
abstract contract AbstractPostDispatchHook is IPostDispatchHook {
using GlobalHookMetadata for bytes;
// ============ External functions ============
/// @inheritdoc IPostDispatchHook
function supportsMetadata(bytes calldata metadata)
public
pure
override
returns (bool)
{
return
metadata.length == 0 ||
metadata.variant() == GlobalHookMetadata.VARIANT;
}
/// @inheritdoc IPostDispatchHook
function postDispatch(bytes calldata metadata, bytes calldata message)
external
payable
override
{
require(
supportsMetadata(metadata),
"AbstractPostDispatchHook: invalid metadata variant"
);
_postDispatch(metadata, message);
}
/// @inheritdoc IPostDispatchHook
function quoteDispatch(bytes calldata metadata, bytes calldata message)
public
view
override
returns (uint256)
{
require(
supportsMetadata(metadata),
"AbstractPostDispatchHook: invalid metadata variant"
);
return _quoteDispatch(metadata, message);
}
// ============ Internal functions ============
/**
* @notice Post dispatch hook implementation.
* @param metadata The metadata of the message being dispatched.
* @param message The message being dispatched.
*/
function _postDispatch(bytes calldata metadata, bytes calldata message)
internal
virtual;
/**
* @notice Quote dispatch hook implementation.
* @param metadata The metadata of the message being dispatched.
* @param message The message being dispatched.
* @return The quote for the dispatch.
*/
function _quoteDispatch(bytes calldata metadata, bytes calldata message)
internal
view
virtual
returns (uint256);
}

@ -14,25 +14,42 @@ pragma solidity >=0.8.0;
@@@@@@@@@ @@@@@@@@*/
import {Message} from "../libs/Message.sol";
import {GlobalHookMetadata} from "../libs/hooks/GlobalHookMetadata.sol";
import {AbstractPostDispatchHook} from "./AbstractPostDispatchHook.sol";
import {MailboxClient} from "../client/MailboxClient.sol";
import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol";
import {IMailbox} from "../interfaces/IMailbox.sol";
contract ConfigFallbackDomainRoutingHook is IPostDispatchHook {
contract ConfigFallbackDomainRoutingHook is
AbstractPostDispatchHook,
MailboxClient
{
using Message for bytes;
using GlobalHookMetadata for bytes;
IMailbox public immutable mailbox;
// ============ Public Storage ============
/// @notice message sender => destination => recipient => hook
mapping(address => mapping(uint32 => mapping(bytes32 => IPostDispatchHook)))
public customHooks;
constructor(address _mailbox) {
mailbox = IMailbox(_mailbox);
constructor(address _mailbox) MailboxClient(_mailbox) {}
// ============ External Functions ============
function setHook(
uint32 destinationDomain,
bytes32 recipient,
IPostDispatchHook hook
) external {
customHooks[msg.sender][destinationDomain][recipient] = hook;
}
function postDispatch(bytes calldata metadata, bytes calldata message)
public
payable
// ============ Internal Functions ============
/// @inheritdoc AbstractPostDispatchHook
function _postDispatch(bytes calldata metadata, bytes calldata message)
internal
override
{
_getConfiguredHook(message).postDispatch{value: msg.value}(
@ -41,24 +58,16 @@ contract ConfigFallbackDomainRoutingHook is IPostDispatchHook {
);
}
function quoteDispatch(bytes calldata metadata, bytes calldata message)
public
/// @inheritdoc AbstractPostDispatchHook
function _quoteDispatch(bytes calldata metadata, bytes calldata message)
internal
view
override
returns (uint256)
{
return _getConfiguredHook(message).quoteDispatch(metadata, message);
}
function setHook(
uint32 destinationDomain,
bytes32 recipient,
IPostDispatchHook hook
) external {
customHooks[msg.sender][destinationDomain][recipient] = hook;
}
// ============ Internal Functions ============
function _getConfiguredHook(bytes calldata message)
internal
view

@ -23,11 +23,12 @@ contract ConfigurableDomainRoutingHook is DomainRoutingHook {
/// @notice mapping of destination domain and recipient to custom hook
mapping(bytes32 => address) public customHooks;
constructor(address mailbox, address owner) DomainRoutingHook(owner) {}
constructor(address mailbox, address owner)
DomainRoutingHook(mailbox, owner)
{}
function postDispatch(bytes calldata metadata, bytes calldata message)
public
payable
function _postDispatch(bytes calldata metadata, bytes calldata message)
internal
override
{
bytes32 hookKey = keccak256(
@ -41,7 +42,7 @@ contract ConfigurableDomainRoutingHook is DomainRoutingHook {
message
);
} else {
super.postDispatch(metadata, message);
super._postDispatch(metadata, message);
}
}

@ -1,14 +1,30 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
/*@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@ HYPERLANE @@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@*/
// ============ Internal Imports ============
import {Message} from "../libs/Message.sol";
import {GlobalHookMetadata} from "../libs/hooks/GlobalHookMetadata.sol";
import {MailboxClient} from "../client/MailboxClient.sol";
import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol";
import {AbstractPostDispatchHook} from "./AbstractPostDispatchHook.sol";
// ============ External Imports ============
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
contract DomainRoutingHook is IPostDispatchHook, Ownable {
contract DomainRoutingHook is AbstractPostDispatchHook, MailboxClient, Ownable {
using GlobalHookMetadata for bytes;
using Message for bytes;
struct HookConfig {
@ -18,7 +34,7 @@ contract DomainRoutingHook is IPostDispatchHook, Ownable {
mapping(uint32 => IPostDispatchHook) public hooks;
constructor(address _owner) {
constructor(address _mailbox, address _owner) MailboxClient(_mailbox) {
_transferOwnership(_owner);
}
@ -32,9 +48,11 @@ contract DomainRoutingHook is IPostDispatchHook, Ownable {
}
}
function postDispatch(bytes calldata metadata, bytes calldata message)
public
payable
// ============ Internal Functions ============
/// @inheritdoc AbstractPostDispatchHook
function _postDispatch(bytes calldata metadata, bytes calldata message)
internal
virtual
override
{
@ -44,8 +62,9 @@ contract DomainRoutingHook is IPostDispatchHook, Ownable {
);
}
function quoteDispatch(bytes calldata metadata, bytes calldata message)
public
/// @inheritdoc AbstractPostDispatchHook
function _quoteDispatch(bytes calldata metadata, bytes calldata message)
internal
view
virtual
override
@ -54,8 +73,6 @@ contract DomainRoutingHook is IPostDispatchHook, Ownable {
return _getConfiguredHook(message).quoteDispatch(metadata, message);
}
// ============ Internal Functions ============
function _getConfiguredHook(bytes calldata message)
internal
view

@ -43,8 +43,8 @@ contract ERC5164Hook is AbstractMessageIdAuthHook {
dispatcher = IMessageDispatcher(_dispatcher);
}
function quoteDispatch(bytes calldata, bytes calldata)
external
function _quoteDispatch(bytes calldata, bytes calldata)
internal
pure
override
returns (uint256)
@ -53,7 +53,8 @@ contract ERC5164Hook is AbstractMessageIdAuthHook {
}
function _sendMessageId(
bytes calldata, /* metadata */
bytes calldata,
/* metadata */
bytes memory payload
) internal override {
require(msg.value == 0, "ERC5164Hook: no value allowed");

@ -1,15 +1,29 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
/*@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@ HYPERLANE @@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@*/
import {MerkleLib} from "../libs/Merkle.sol";
import {Message} from "../libs/Message.sol";
import {MailboxClient} from "../client/MailboxClient.sol";
import {Indexed} from "../Indexed.sol";
import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol";
import {AbstractPostDispatchHook} from "./AbstractPostDispatchHook.sol";
import {GlobalHookMetadata} from "../libs/hooks/GlobalHookMetadata.sol";
contract MerkleTreeHook is IPostDispatchHook, MailboxClient, Indexed {
contract MerkleTreeHook is AbstractPostDispatchHook, MailboxClient, Indexed {
using Message for bytes;
using MerkleLib for MerkleLib.Tree;
using GlobalHookMetadata for bytes;
// An incremental merkle tree used to store outbound message IDs.
MerkleLib.Tree internal _tree;
@ -34,10 +48,14 @@ contract MerkleTreeHook is IPostDispatchHook, MailboxClient, Indexed {
return (root(), count() - 1);
}
function postDispatch(
bytes calldata, /*metadata*/
// ============ Internal Functions ============
/// @inheritdoc AbstractPostDispatchHook
function _postDispatch(
bytes calldata,
/*metadata*/
bytes calldata message
) external payable override {
) internal override {
require(msg.value == 0, "MerkleTreeHook: no value expected");
bytes32 id = message.id();
require(isLatestDispatched(id), "message not dispatching");
@ -46,10 +64,12 @@ contract MerkleTreeHook is IPostDispatchHook, MailboxClient, Indexed {
emit InsertedIntoTree(id, count() - 1);
}
function quoteDispatch(
bytes calldata, /*metadata*/
/// @inheritdoc AbstractPostDispatchHook
function _quoteDispatch(
bytes calldata,
/*metadata*/
bytes calldata /*message*/
) external pure override returns (uint256) {
) internal pure override returns (uint256) {
return 0;
}
}

@ -17,7 +17,7 @@ pragma solidity >=0.8.0;
import {AbstractMessageIdAuthHook} from "./AbstractMessageIdAuthHook.sol";
import {TypeCasts} from "../libs/TypeCasts.sol";
import {Message} from "../libs/Message.sol";
import {OPStackHookMetadata} from "../libs/hooks/OPStackHookMetadata.sol";
import {GlobalHookMetadata} from "../libs/hooks/GlobalHookMetadata.sol";
import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol";
// ============ External Imports ============
@ -30,7 +30,7 @@ import {Address} from "@openzeppelin/contracts/utils/Address.sol";
* the native OPStack bridge.
*/
contract OPStackHook is AbstractMessageIdAuthHook {
using OPStackHookMetadata for bytes;
using GlobalHookMetadata for bytes;
// ============ Constants ============
@ -59,9 +59,8 @@ contract OPStackHook is AbstractMessageIdAuthHook {
// ============ External functions ============
/// @inheritdoc IPostDispatchHook
function quoteDispatch(bytes calldata, bytes calldata)
external
function _quoteDispatch(bytes calldata, bytes calldata)
internal
pure
override
returns (uint256)
@ -77,10 +76,10 @@ contract OPStackHook is AbstractMessageIdAuthHook {
override
{
require(
metadata.msgValue() < 2**255,
metadata.msgValue(0) < 2**255,
"OPStackHook: msgValue must less than 2 ** 255"
);
l1Messenger.sendMessage{value: metadata.msgValue()}(
l1Messenger.sendMessage{value: metadata.msgValue(0)}(
ism,
payload,
GAS_LIMIT

@ -1,27 +1,28 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol";
/*@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@ HYPERLANE @@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@*/
import {GlobalHookMetadata} from "../libs/hooks/GlobalHookMetadata.sol";
import {AbstractPostDispatchHook} from "./AbstractPostDispatchHook.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol";
contract PausableHook is IPostDispatchHook, Ownable, Pausable {
function postDispatch(bytes calldata metadata, bytes calldata message)
external
payable
whenNotPaused
{}
contract PausableHook is AbstractPostDispatchHook, Ownable, Pausable {
using GlobalHookMetadata for bytes;
/// @inheritdoc IPostDispatchHook
function quoteDispatch(bytes calldata, bytes calldata)
external
pure
override
returns (uint256)
{
return 0;
}
// ============ External functions ============
function pause() external onlyOwner {
_pause();
@ -30,4 +31,23 @@ contract PausableHook is IPostDispatchHook, Ownable, Pausable {
function unpause() external onlyOwner {
_unpause();
}
// ============ Internal functions ============
/// @inheritdoc AbstractPostDispatchHook
function _postDispatch(bytes calldata metadata, bytes calldata message)
internal
override
whenNotPaused
{}
/// @inheritdoc AbstractPostDispatchHook
function _quoteDispatch(bytes calldata, bytes calldata)
internal
pure
override
returns (uint256)
{
return 0;
}
}

@ -15,7 +15,8 @@ pragma solidity >=0.8.0;
// ============ Internal Imports ============
import {Message} from "../libs/Message.sol";
import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol";
import {GlobalHookMetadata} from "../libs/hooks/GlobalHookMetadata.sol";
import {AbstractPostDispatchHook} from "./AbstractPostDispatchHook.sol";
// ============ External Imports ============
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
@ -25,7 +26,8 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
* @notice Collects a static protocol fee from the sender.
* @dev V3 WIP
*/
contract StaticProtocolFee is IPostDispatchHook, Ownable {
contract StaticProtocolFee is AbstractPostDispatchHook, Ownable {
using GlobalHookMetadata for bytes;
using Address for address payable;
using Message for bytes;
@ -57,33 +59,6 @@ contract StaticProtocolFee is IPostDispatchHook, Ownable {
// ============ External Functions ============
/**
* @notice Collects the protocol fee from the sender.
*/
function postDispatch(bytes calldata, bytes calldata message)
external
payable
override
{
require(
msg.value >= protocolFee,
"StaticProtocolFee: insufficient protocol fee"
);
uint256 refund = msg.value - protocolFee;
if (refund > 0) payable(message.senderAddress()).sendValue(refund);
}
/// @inheritdoc IPostDispatchHook
function quoteDispatch(bytes calldata, bytes calldata)
external
view
override
returns (uint256)
{
return protocolFee;
}
/**
* @notice Sets the protocol fee.
* @param _protocolFee The new protocol fee.
@ -109,6 +84,33 @@ contract StaticProtocolFee is IPostDispatchHook, Ownable {
// ============ Internal Functions ============
/// @inheritdoc AbstractPostDispatchHook
function _postDispatch(bytes calldata metadata, bytes calldata message)
internal
override
{
require(
msg.value >= protocolFee,
"StaticProtocolFee: insufficient protocol fee"
);
uint256 refund = msg.value - protocolFee;
if (refund > 0)
payable(metadata.refundAddress(message.senderAddress())).sendValue(
refund
);
}
/// @inheritdoc AbstractPostDispatchHook
function _quoteDispatch(bytes calldata, bytes calldata)
internal
view
override
returns (uint256)
{
return protocolFee;
}
/**
* @notice Sets the protocol fee.
* @param _protocolFee The new protocol fee.

@ -13,13 +13,19 @@ pragma solidity >=0.8.0;
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@*/
import {GlobalHookMetadata} from "../../libs/hooks/GlobalHookMetadata.sol";
import {IPostDispatchHook} from "../../interfaces/hooks/IPostDispatchHook.sol";
import {AbstractPostDispatchHook} from "../AbstractPostDispatchHook.sol";
import {MetaProxy} from "../../libs/MetaProxy.sol";
contract StaticAggregationHook is IPostDispatchHook {
function postDispatch(bytes calldata metadata, bytes calldata message)
external
payable
contract StaticAggregationHook is AbstractPostDispatchHook {
using GlobalHookMetadata for bytes;
// ============ External functions ============
/// @inheritdoc AbstractPostDispatchHook
function _postDispatch(bytes calldata metadata, bytes calldata message)
internal
override
{
address[] memory _hooks = hooks(message);
@ -37,8 +43,9 @@ contract StaticAggregationHook is IPostDispatchHook {
}
}
function quoteDispatch(bytes calldata metadata, bytes calldata message)
external
/// @inheritdoc AbstractPostDispatchHook
function _quoteDispatch(bytes calldata metadata, bytes calldata message)
internal
view
override
returns (uint256)

@ -1,5 +1,18 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.8.0;
/*@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@ HYPERLANE @@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@*/
// ============ Internal Imports ============
import {StaticAggregationHook} from "./StaticAggregationHook.sol";
import {StaticNAddressSetFactory} from "../../libs/StaticNAddressSetFactory.sol";

@ -15,10 +15,12 @@ pragma solidity >=0.8.0;
// ============ Internal Imports ============
import {Message} from "../libs/Message.sol";
import {IGPMetadata} from "../libs/hooks/IGPMetadata.sol";
import {GlobalHookMetadata} from "../libs/hooks/GlobalHookMetadata.sol";
import {GlobalHookMetadata} from "../libs/hooks/GlobalHookMetadata.sol";
import {IGasOracle} from "../interfaces/IGasOracle.sol";
import {IInterchainGasPaymaster} from "../interfaces/IInterchainGasPaymaster.sol";
import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol";
import {AbstractPostDispatchHook} from "../hooks/AbstractPostDispatchHook.sol";
import {Indexed} from "../Indexed.sol";
// ============ External Imports ============
@ -33,14 +35,14 @@ import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Own
*/
contract InterchainGasPaymaster is
IInterchainGasPaymaster,
IPostDispatchHook,
AbstractPostDispatchHook,
IGasOracle,
Indexed,
OwnableUpgradeable
{
using Address for address payable;
using Message for bytes;
using IGPMetadata for bytes;
using GlobalHookMetadata for bytes;
// ============ Constants ============
/// @notice The scale of gas oracle token exchange rates.
@ -91,36 +93,6 @@ contract InterchainGasPaymaster is
_setBeneficiary(_beneficiary);
}
/**
* @notice pay for gas as a hook
* @param metadata The metadata as gasConfig.
* @param message The message to pay for.
*/
function postDispatch(bytes calldata metadata, bytes calldata message)
external
payable
override
{
uint256 gasLimit = metadata.gasLimit(DEFAULT_GAS_USAGE);
address refundAddress = metadata.refundAddress(message.senderAddress());
payForGas(message.id(), message.destination(), gasLimit, refundAddress);
}
/**
* @notice Quote gas payment for a hook call.
* @param metadata The metadata as gasConfig.
* @param message The message to pay for.
*/
function quoteDispatch(bytes calldata metadata, bytes calldata message)
external
view
override
returns (uint256)
{
uint256 gasLimit = metadata.gasLimit(DEFAULT_GAS_USAGE);
return quoteGasPayment(message.destination(), gasLimit);
}
/**
* @notice Transfers the entire native token balance to the beneficiary.
* @dev The beneficiary must be able to receive native tokens.
@ -248,6 +220,27 @@ contract InterchainGasPaymaster is
// ============ Internal Functions ============
/// @inheritdoc AbstractPostDispatchHook
function _postDispatch(bytes calldata metadata, bytes calldata message)
internal
override
{
uint256 gasLimit = metadata.gasLimit(DEFAULT_GAS_USAGE);
address refundAddress = metadata.refundAddress(message.senderAddress());
payForGas(message.id(), message.destination(), gasLimit, refundAddress);
}
/// @inheritdoc AbstractPostDispatchHook
function _quoteDispatch(bytes calldata metadata, bytes calldata message)
internal
view
override
returns (uint256)
{
uint256 gasLimit = metadata.gasLimit(DEFAULT_GAS_USAGE);
return quoteGasPayment(message.destination(), gasLimit);
}
/**
* @notice Sets the beneficiary.
* @param _beneficiary The new beneficiary.

@ -1,7 +1,29 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.8.0;
/*@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@ HYPERLANE @@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@*/
interface IPostDispatchHook {
/**
* @notice Returns whether the hook supports metadata
* @param metadata metadata
* @return Whether the hook supports metadata
*/
function supportsMetadata(bytes calldata metadata)
external
view
returns (bool);
/**
* @notice Post action afte a message is dispatched via the Mailbox
* @param metadata The metadata required for the hook

@ -0,0 +1,164 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.8.0;
/*@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@ HYPERLANE @@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@*/
/**
* Format of metadata:
*
* [0:1] variant
* [2:33] msg.value
* [34:65] Gas limit for message (IGP)
* [66:85] Refund address for message (IGP)
* [86:] Custom metadata
*/
library GlobalHookMetadata {
uint8 private constant VARIANT_OFFSET = 0;
uint8 private constant MSG_VALUE_OFFSET = 2;
uint8 private constant GAS_LIMIT_OFFSET = 34;
uint8 private constant REFUND_ADDRESS_OFFSET = 66;
uint256 private constant MIN_METADATA_LENGTH = 86;
uint16 public constant VARIANT = 1;
/**
* @notice Returns the variant of the metadata.
* @param _metadata ABI encoded global hook metadata.
* @return variant of the metadata as uint8.
*/
function variant(bytes calldata _metadata) internal pure returns (uint16) {
if (_metadata.length < VARIANT_OFFSET + 2) return 0;
return uint16(bytes2(_metadata[VARIANT_OFFSET:VARIANT_OFFSET + 2]));
}
/**
* @notice Returns the specified value for the message.
* @param _metadata ABI encoded global hook metadata.
* @return Value for the message as uint256.
*/
function msgValue(bytes calldata _metadata, uint256 _default)
internal
pure
returns (uint256)
{
if (_metadata.length < MSG_VALUE_OFFSET + 32) return _default;
return
uint256(bytes32(_metadata[MSG_VALUE_OFFSET:MSG_VALUE_OFFSET + 32]));
}
/**
* @notice Returns the specified gas limit for the message.
* @param _metadata ABI encoded global hook metadata.
* @return Gas limit for the message as uint256.
*/
function gasLimit(bytes calldata _metadata, uint256 _default)
internal
pure
returns (uint256)
{
if (_metadata.length < GAS_LIMIT_OFFSET + 32) return _default;
return
uint256(bytes32(_metadata[GAS_LIMIT_OFFSET:GAS_LIMIT_OFFSET + 32]));
}
/**
* @notice Returns the specified refund address for the message.
* @param _metadata ABI encoded global hook metadata.
* @return Refund address for the message as address.
*/
function refundAddress(bytes calldata _metadata, address _default)
internal
pure
returns (address)
{
if (_metadata.length < REFUND_ADDRESS_OFFSET + 20) return _default;
return
address(
bytes20(
_metadata[REFUND_ADDRESS_OFFSET:REFUND_ADDRESS_OFFSET + 20]
)
);
}
/**
* @notice Returns the specified refund address for the message.
* @param _metadata ABI encoded global hook metadata.
* @return Refund address for the message as address.
*/
function getCustomMetadata(bytes calldata _metadata)
internal
pure
returns (bytes calldata)
{
if (_metadata.length < MIN_METADATA_LENGTH) return _metadata[0:0];
return _metadata[MIN_METADATA_LENGTH:];
}
/**
* @notice Formats the specified gas limit and refund address into global hook metadata.
* @param _msgValue msg.value for the message.
* @param _gasLimit Gas limit for the message.
* @param _refundAddress Refund address for the message.
* @param _customMetadata Additional metadata to include in the global hook metadata.
* @return ABI encoded global hook metadata.
*/
function formatMetadata(
uint256 _msgValue,
uint256 _gasLimit,
address _refundAddress,
bytes memory _customMetadata
) internal pure returns (bytes memory) {
return
abi.encodePacked(
VARIANT,
_msgValue,
_gasLimit,
_refundAddress,
_customMetadata
);
}
/**
* @notice Formats the specified gas limit and refund address into global hook metadata.
* @param _msgValue msg.value for the message.
* @return ABI encoded global hook metadata.
*/
function formatMetadata(uint256 _msgValue)
internal
view
returns (bytes memory)
{
return abi.encodePacked(VARIANT, _msgValue, uint256(0), msg.sender, "");
}
/**
* @notice Formats the specified gas limit and refund address into global hook metadata.
* @param _gasLimit Gas limit for the message.
* @param _refundAddress Refund address for the message.
* @return ABI encoded global hook metadata.
*/
function formatMetadata(uint256 _gasLimit, address _refundAddress)
internal
pure
returns (bytes memory)
{
return
abi.encodePacked(
VARIANT,
uint256(0),
_gasLimit,
_refundAddress,
""
);
}
}

@ -1,78 +0,0 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.8.0;
/*@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@ HYPERLANE @@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@*/
/**
* Format of metadata:
*
* [0:32] Gas limit for message
* [32:52] Refund address for message
*/
library IGPMetadata {
uint8 private constant GAS_LIMIT_OFFSET = 0;
uint8 private constant REFUND_ADDRESS_OFFSET = 32;
/**
* @notice Returns the specified gas limit for the message.
* @param _metadata ABI encoded IGP hook metadata.
* @return Gas limit for the message as uint256.
*/
function gasLimit(bytes calldata _metadata, uint256 _default)
internal
pure
returns (uint256)
{
if (_metadata.length < GAS_LIMIT_OFFSET + 32) return _default;
return
uint256(bytes32(_metadata[GAS_LIMIT_OFFSET:GAS_LIMIT_OFFSET + 32]));
}
/**
* @notice Returns the specified refund address for the message.
* @param _metadata ABI encoded IGP hook metadata.
* @return Refund address for the message as address.
*/
function refundAddress(bytes calldata _metadata, address _default)
internal
pure
returns (address)
{
address _refundAddress;
if (_metadata.length < REFUND_ADDRESS_OFFSET + 20) {
_refundAddress = _default;
} else {
_refundAddress = address(
bytes20(
_metadata[REFUND_ADDRESS_OFFSET:REFUND_ADDRESS_OFFSET + 20]
)
);
if (_refundAddress == address(0)) _refundAddress = _default;
}
return _refundAddress;
}
/**
* @notice Formats the specified gas limit and refund address into IGP hook metadata.
* @param _gasLimit Gas limit for the message.
* @param _refundAddress Refund address for the message.
* @return ABI encoded IGP hook metadata.
*/
function formatMetadata(uint256 _gasLimit, address _refundAddress)
internal
pure
returns (bytes memory)
{
return abi.encodePacked(bytes32(_gasLimit), bytes20(_refundAddress));
}
}

@ -1,17 +0,0 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.8.0;
/**
* Format of metadata:
*
* [0:32] Msg value to be sent to L2
*/
library OPStackHookMetadata {
function msgValue(bytes calldata _metadata)
internal
pure
returns (uint256)
{
return uint256(bytes32(_metadata[0:32]));
}
}

@ -1,15 +1,23 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.8.0;
import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol";
import {AbstractPostDispatchHook} from "../hooks/AbstractPostDispatchHook.sol";
import {GlobalHookMetadata} from "../libs/hooks/GlobalHookMetadata.sol";
contract TestPostDispatchHook is IPostDispatchHook {
contract TestPostDispatchHook is AbstractPostDispatchHook {
using GlobalHookMetadata for bytes;
// ============ Public Storage ============
// test fees for quoteDispatch
uint256 public fee = 25000;
function postDispatch(
bytes calldata, /*metadata*/
// ============ Internal functions ============
function _postDispatch(
bytes calldata,
/*metadata*/
bytes calldata /*message*/
) external payable {
) internal pure override {
// test - empty
}
@ -17,10 +25,11 @@ contract TestPostDispatchHook is IPostDispatchHook {
fee = _fee;
}
function quoteDispatch(
bytes calldata, /*metadata*/
function _quoteDispatch(
bytes calldata,
/*metadata*/
bytes calldata /*message*/
) external view override returns (uint256) {
) internal view override returns (uint256) {
return fee;
}
}

@ -4,14 +4,17 @@ pragma solidity ^0.8.13;
import "forge-std/Test.sol";
import "../contracts/test/TestMailbox.sol";
import "../contracts/upgrade/Versioned.sol";
import "../contracts/interfaces/hooks/IPostDispatchHook.sol";
import "../contracts/test/TestPostDispatchHook.sol";
import "../contracts/test/TestIsm.sol";
import "../contracts/test/TestRecipient.sol";
import "../contracts/hooks/MerkleTreeHook.sol";
import {GlobalHookMetadata} from "../contracts/libs/hooks/GlobalHookMetadata.sol";
import {TypeCasts} from "../contracts/libs/TypeCasts.sol";
contract MailboxTest is Test, Versioned {
using GlobalHookMetadata for bytes;
using TypeCasts for address;
using Message for bytes;
@ -144,7 +147,7 @@ contract MailboxTest is Test, Versioned {
function expectHookQuote(
IPostDispatchHook hook,
bytes calldata metadata,
bytes memory metadata,
bytes memory message
) internal {
vm.expectCall(
@ -155,7 +158,7 @@ contract MailboxTest is Test, Versioned {
function expectHookPost(
IPostDispatchHook hook,
bytes calldata metadata,
bytes memory metadata,
bytes memory message,
uint256 value
) internal {
@ -173,6 +176,10 @@ contract MailboxTest is Test, Versioned {
bytes calldata body,
bytes calldata metadata
) public {
bytes memory prefixedMetadata = abi.encodePacked(
GlobalHookMetadata.VARIANT,
metadata
);
vm.assume(
requiredFee < type(uint128).max &&
defaultFee < type(uint128).max &&
@ -198,23 +205,23 @@ contract MailboxTest is Test, Versioned {
);
assertEq(quote, defaultFee + requiredFee);
expectHookQuote(requiredHook, metadata, message);
expectHookQuote(defaultHook, metadata, message);
expectHookQuote(requiredHook, prefixedMetadata, message);
expectHookQuote(defaultHook, prefixedMetadata, message);
quote = mailbox.quoteDispatch(
remoteDomain,
address(recipient).addressToBytes32(),
body,
metadata
prefixedMetadata
);
assertEq(quote, defaultFee + requiredFee);
expectHookQuote(requiredHook, metadata, message);
expectHookQuote(overrideHook, metadata, message);
expectHookQuote(requiredHook, prefixedMetadata, message);
expectHookQuote(overrideHook, prefixedMetadata, message);
quote = mailbox.quoteDispatch(
remoteDomain,
address(recipient).addressToBytes32(),
body,
metadata,
prefixedMetadata,
overrideHook
);
assertEq(quote, overrideFee + requiredFee);
@ -232,7 +239,7 @@ contract MailboxTest is Test, Versioned {
function expectDispatch(
TestPostDispatchHook firstHook,
TestPostDispatchHook hook,
bytes calldata metadata,
bytes memory metadata,
bytes calldata body
) internal {
bytes memory message = mailbox.buildOutboundMessage(
@ -254,6 +261,10 @@ contract MailboxTest is Test, Versioned {
bytes calldata body,
bytes calldata metadata
) public {
bytes memory prefixedMetadata = abi.encodePacked(
GlobalHookMetadata.VARIANT,
metadata
);
bytes calldata defaultMetadata = metadata[0:0];
uint256 quote;
uint32 nonce;
@ -280,14 +291,14 @@ contract MailboxTest is Test, Versioned {
remoteDomain,
recipientb32,
body,
metadata
prefixedMetadata
);
expectDispatch(requiredHook, defaultHook, metadata, body);
expectDispatch(requiredHook, defaultHook, prefixedMetadata, body);
id = mailbox.dispatch{value: quote}(
remoteDomain,
recipientb32,
body,
metadata
prefixedMetadata
);
assertEq(mailbox.latestDispatchedId(), id);
nonce = mailbox.nonce();
@ -298,15 +309,15 @@ contract MailboxTest is Test, Versioned {
remoteDomain,
recipientb32,
body,
metadata,
prefixedMetadata,
overrideHook
);
expectDispatch(requiredHook, overrideHook, metadata, body);
expectDispatch(requiredHook, overrideHook, prefixedMetadata, body);
id = mailbox.dispatch{value: quote}(
remoteDomain,
recipientb32,
body,
metadata,
prefixedMetadata,
overrideHook
);
assertEq(mailbox.latestDispatchedId(), id);

@ -4,11 +4,13 @@ pragma solidity ^0.8.13;
import {Test} from "forge-std/Test.sol";
import {TypeCasts} from "../../contracts/libs/TypeCasts.sol";
import {MessageUtils} from "../isms/IsmTestUtils.sol";
import {GlobalHookMetadata} from "../../contracts/libs/hooks/GlobalHookMetadata.sol";
import {StaticProtocolFee} from "../../contracts/hooks/StaticProtocolFee.sol";
contract StaticProtocolFeeTest is Test {
using TypeCasts for address;
StaticProtocolFee internal fees;
address internal alice = address(0x1); // alice the user
@ -108,6 +110,32 @@ contract StaticProtocolFeeTest is Test {
assertEq(alice.balance, aliceBalanceBefore - feeRequired);
}
function test_postDispatch_specifyRefundAddress(
uint256 feeRequired,
uint256 feeSent
) public {
bytes memory metadata = GlobalHookMetadata.formatMetadata(
0,
0,
bob,
""
);
feeRequired = bound(feeRequired, 1, fees.MAX_PROTOCOL_FEE());
feeSent = bound(feeSent, feeRequired, 10 * feeRequired);
vm.deal(alice, feeSent);
fees.setProtocolFee(feeRequired);
uint256 aliceBalanceBefore = alice.balance;
uint256 bobBalanceBefore = bob.balance;
vm.prank(alice);
fees.postDispatch{value: feeSent}(metadata, testMessage);
assertEq(alice.balance, aliceBalanceBefore - feeSent);
assertEq(bob.balance, bobBalanceBefore + feeSent - feeRequired);
}
function testFuzz_collectProtocolFee(
uint256 feeRequired,
uint256 dispatchCalls

@ -3,7 +3,7 @@ pragma solidity ^0.8.13;
import {Test} from "forge-std/Test.sol";
import {IGPMetadata} from "../../contracts/libs/hooks/IGPMetadata.sol";
import {GlobalHookMetadata} from "../../contracts/libs/hooks/GlobalHookMetadata.sol";
import {Message} from "../../contracts/libs/Message.sol";
import {MessageUtils} from "../isms/IsmTestUtils.sol";
import {TypeCasts} from "../../contracts/libs/TypeCasts.sol";
@ -12,7 +12,7 @@ import {StorageGasOracle} from "../../contracts/igps/gas-oracles/StorageGasOracl
import {IGasOracle} from "../../contracts/interfaces/IGasOracle.sol";
contract InterchainGasPaymasterTest is Test {
using IGPMetadata for bytes;
using GlobalHookMetadata for bytes;
using TypeCasts for address;
using MessageUtils for bytes;
@ -90,9 +90,11 @@ contract InterchainGasPaymasterTest is Test {
150 // 1 wei gas price
);
bytes memory metadata = IGPMetadata.formatMetadata(
bytes memory metadata = GlobalHookMetadata.formatMetadata(
0,
uint256(testGasAmount), // gas limit
testRefundAddress // refund address
testRefundAddress, // refund address,
bytes("")
);
// 150 * 300_000 = 45_000_000
assertEq(igp.quoteDispatch(metadata, testEncodedMessage), 45_000_000);
@ -139,9 +141,11 @@ contract InterchainGasPaymasterTest is Test {
);
uint256 _overpayment = 25000;
bytes memory metadata = IGPMetadata.formatMetadata(
bytes memory metadata = GlobalHookMetadata.formatMetadata(
0,
uint256(testGasAmount), // gas limit
testRefundAddress // refund address
testRefundAddress, // refund address
bytes("")
);
bytes memory message = _encodeTestMessage();

@ -5,6 +5,8 @@ import {Test} from "forge-std/Test.sol";
import {LibBit} from "../../contracts/libs/LibBit.sol";
import {TypeCasts} from "../../contracts/libs/TypeCasts.sol";
import {GlobalHookMetadata} from "../../contracts/libs/hooks/GlobalHookMetadata.sol";
import {GlobalHookMetadata} from "../../contracts/libs/hooks/GlobalHookMetadata.sol";
import {AbstractMessageIdAuthorizedIsm} from "../../contracts/isms/hook/AbstractMessageIdAuthorizedIsm.sol";
import {TestMailbox} from "../../contracts/test/TestMailbox.sol";
import {Message} from "../../contracts/libs/Message.sol";
@ -33,7 +35,8 @@ contract OPStackIsmTest is Test {
address internal constant L2_MESSENGER_ADDRESS =
0x4200000000000000000000000000000000000007;
uint8 internal constant VERSION = 0;
uint8 internal constant OPTIMISM_VERSION = 0;
uint8 internal constant HYPERLANE_VERSION = 1;
uint256 internal constant DEFAULT_GAS_LIMIT = 1_920_000;
address internal alice = address(0x1);
@ -47,7 +50,8 @@ contract OPStackIsmTest is Test {
TestRecipient internal testRecipient;
bytes internal testMessage =
abi.encodePacked("Hello from the other chain!");
bytes internal testMetadata = abi.encodePacked(uint256(0));
bytes internal testMetadata =
GlobalHookMetadata.formatMetadata(0, 0, address(this), "");
bytes internal encodedMessage;
bytes32 internal messageId;
@ -169,7 +173,7 @@ contract OPStackIsmTest is Test {
vm.selectFork(mainnetFork);
bytes memory message = MessageUtils.formatMessage(
VERSION,
OPTIMISM_VERSION,
uint32(0),
MAINNET_DOMAIN,
TypeCasts.addressToBytes32(address(this)),
@ -191,8 +195,11 @@ contract OPStackIsmTest is Test {
vm.selectFork(mainnetFork);
vm.deal(address(this), uint256(2**255 + 1));
bytes memory excessValueMetadata = abi.encodePacked(
uint256(2**255 + 1)
bytes memory excessValueMetadata = GlobalHookMetadata.formatMetadata(
uint256(2**255 + 1),
DEFAULT_GAS_LIMIT,
address(this),
""
);
l1Mailbox.updateLatestDispatchedId(messageId);
@ -377,7 +384,7 @@ contract OPStackIsmTest is Test {
);
bytes memory invalidMessage = MessageUtils.formatMessage(
VERSION,
HYPERLANE_VERSION,
uint8(0),
MAINNET_DOMAIN,
TypeCasts.addressToBytes32(address(this)),
@ -395,7 +402,7 @@ contract OPStackIsmTest is Test {
vm.selectFork(optimismFork);
bytes memory invalidMessage = MessageUtils.formatMessage(
VERSION,
HYPERLANE_VERSION,
uint8(0),
MAINNET_DOMAIN,
TypeCasts.addressToBytes32(address(this)),
@ -434,7 +441,7 @@ contract OPStackIsmTest is Test {
function _encodeTestMessage() internal view returns (bytes memory) {
return
MessageUtils.formatMessage(
VERSION,
HYPERLANE_VERSION,
uint32(0),
MAINNET_DOMAIN,
TypeCasts.addressToBytes32(address(this)),

Loading…
Cancel
Save