Skip to content

Commit

Permalink
Hook metadata improvements (#2953)
Browse files Browse the repository at this point in the history
### Description

- Improves `StandardHookMetadata` interface to be more explicit
 
### Drive-by changes

- Update usage across hooks and routers

### Related issues

- Touches hyperlane-xyz/issues#726

### Backward compatibility

- No but minimally used

### Testing

Unit Tests
  • Loading branch information
yorhodes authored Nov 22, 2023
2 parents 97f4c94 + 6044fb8 commit 83335b4
Show file tree
Hide file tree
Showing 13 changed files with 56 additions and 73 deletions.
6 changes: 6 additions & 0 deletions .changeset/good-candles-promise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@hyperlane-xyz/helloworld': patch
'@hyperlane-xyz/core': patch
---

Improve client side StandardHookMetadata library interface
9 changes: 1 addition & 8 deletions solidity/contracts/client/GasRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,11 @@ abstract contract GasRouter is Router {
return _quoteDispatch(_destinationDomain, "");
}

function _refundAddress(uint32) internal view virtual returns (address) {
return msg.sender;
}

function _metadata(
uint32 _destination
) internal view virtual override returns (bytes memory) {
return
StandardHookMetadata.formatMetadata(
destinationGas[_destination],
_refundAddress(_destination)
);
StandardHookMetadata.overrideGasLimit(destinationGas[_destination]);
}

function _setDestinationGas(uint32 domain, uint256 gas) internal {
Expand Down
1 change: 0 additions & 1 deletion solidity/contracts/client/Router.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol";
import {IInterchainSecurityModule} from "../interfaces/IInterchainSecurityModule.sol";
import {MailboxClient} from "./MailboxClient.sol";
import {EnumerableMapExtended} from "../libs/EnumerableMapExtended.sol";
import {StandardHookMetadata} from "../hooks/libs/StandardHookMetadata.sol";

// ============ External Imports ============
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
Expand Down
3 changes: 0 additions & 3 deletions solidity/contracts/hooks/PausableHook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,13 @@ pragma solidity >=0.8.0;
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@*/

import {StandardHookMetadata} from "../hooks/libs/StandardHookMetadata.sol";
import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol";
import {AbstractPostDispatchHook} from "./libs/AbstractPostDispatchHook.sol";

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol";

contract PausableHook is AbstractPostDispatchHook, Ownable, Pausable {
using StandardHookMetadata for bytes;

// ============ External functions ============

function pause() external onlyOwner {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,11 @@ pragma solidity >=0.8.0;
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@*/

import {StandardHookMetadata} from "../libs/StandardHookMetadata.sol";
import {AbstractPostDispatchHook} from "../libs/AbstractPostDispatchHook.sol";
import {IPostDispatchHook} from "../../interfaces/hooks/IPostDispatchHook.sol";
import {MetaProxy} from "../../libs/MetaProxy.sol";

contract StaticAggregationHook is AbstractPostDispatchHook {
using StandardHookMetadata for bytes;

// ============ External functions ============

/// @inheritdoc IPostDispatchHook
Expand Down
56 changes: 36 additions & 20 deletions solidity/contracts/hooks/libs/StandardHookMetadata.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,20 @@ pragma solidity >=0.8.0;
/**
* Format of metadata:
*
* [0:1] variant
* [2:33] msg.value
* [34:65] Gas limit for message (IGP)
* [66:85] Refund address for message (IGP)
* [0:2] variant
* [2:34] msg.value
* [34:66] Gas limit for message (IGP)
* [66:86] Refund address for message (IGP)
* [86:] Custom metadata
*/
library StandardHookMetadata {
struct Metadata {
uint16 variant;
uint256 msgValue;
uint256 gasLimit;
address refundAddress;
}

uint8 private constant VARIANT_OFFSET = 0;
uint8 private constant MSG_VALUE_OFFSET = 2;
uint8 private constant GAS_LIMIT_OFFSET = 34;
Expand All @@ -33,7 +40,7 @@ library StandardHookMetadata {

/**
* @notice Returns the variant of the metadata.
* @param _metadata ABI encoded global hook metadata.
* @param _metadata ABI encoded standard hook metadata.
* @return variant of the metadata as uint8.
*/
function variant(bytes calldata _metadata) internal pure returns (uint16) {
Expand All @@ -43,7 +50,7 @@ library StandardHookMetadata {

/**
* @notice Returns the specified value for the message.
* @param _metadata ABI encoded global hook metadata.
* @param _metadata ABI encoded standard hook metadata.
* @param _default Default fallback value.
* @return Value for the message as uint256.
*/
Expand All @@ -58,7 +65,7 @@ library StandardHookMetadata {

/**
* @notice Returns the specified gas limit for the message.
* @param _metadata ABI encoded global hook metadata.
* @param _metadata ABI encoded standard hook metadata.
* @param _default Default fallback gas limit.
* @return Gas limit for the message as uint256.
*/
Expand All @@ -73,7 +80,7 @@ library StandardHookMetadata {

/**
* @notice Returns the specified refund address for the message.
* @param _metadata ABI encoded global hook metadata.
* @param _metadata ABI encoded standard hook metadata.
* @param _default Default fallback refund address.
* @return Refund address for the message as address.
*/
Expand All @@ -92,7 +99,7 @@ library StandardHookMetadata {

/**
* @notice Returns the specified refund address for the message.
* @param _metadata ABI encoded global hook metadata.
* @param _metadata ABI encoded standard hook metadata.
* @return Refund address for the message as address.
*/
function getCustomMetadata(
Expand All @@ -103,12 +110,12 @@ library StandardHookMetadata {
}

/**
* @notice Formats the specified gas limit and refund address into global hook metadata.
* @notice Formats the specified gas limit and refund address into standard 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.
* @param _customMetadata Additional metadata to include in the standard hook metadata.
* @return ABI encoded standard hook metadata.
*/
function formatMetadata(
uint256 _msgValue,
Expand All @@ -127,26 +134,35 @@ library StandardHookMetadata {
}

/**
* @notice Formats the specified gas limit and refund address into global hook metadata.
* @notice Formats the specified gas limit and refund address into standard hook metadata.
* @param _msgValue msg.value for the message.
* @return ABI encoded global hook metadata.
* @return ABI encoded standard hook metadata.
*/
function formatMetadata(
function overrideMsgValue(
uint256 _msgValue
) internal view returns (bytes memory) {
return formatMetadata(_msgValue, uint256(0), msg.sender, "");
}

/**
* @notice Formats the specified gas limit and refund address into global hook metadata.
* @notice Formats the specified gas limit and refund address into standard hook metadata.
* @param _gasLimit Gas limit for the message.
* @return ABI encoded standard hook metadata.
*/
function overrideGasLimit(
uint256 _gasLimit
) internal view returns (bytes memory) {
return formatMetadata(uint256(0), _gasLimit, msg.sender, "");
}

/**
* @notice Formats the specified refund address into standard hook metadata.
* @param _refundAddress Refund address for the message.
* @return ABI encoded global hook metadata.
* @return ABI encoded standard hook metadata.
*/
function formatMetadata(
uint256 _gasLimit,
function overrideRefundAddress(
address _refundAddress
) internal pure returns (bytes memory) {
return formatMetadata(uint256(0), _gasLimit, _refundAddress, "");
return formatMetadata(uint256(0), uint256(0), _refundAddress, "");
}
}
1 change: 0 additions & 1 deletion solidity/contracts/hooks/routing/DomainRoutingHook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ pragma solidity >=0.8.0;
@@@@@@@@@ @@@@@@@@*/

// ============ Internal Imports ============
import {StandardHookMetadata} from "../libs/StandardHookMetadata.sol";
import {AbstractPostDispatchHook} from "../libs/AbstractPostDispatchHook.sol";
import {MailboxClient} from "../../client/MailboxClient.sol";
import {Message} from "../../libs/Message.sol";
Expand Down
2 changes: 2 additions & 0 deletions solidity/contracts/interfaces/IMailbox.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ interface IMailbox {

function defaultHook() external view returns (IPostDispatchHook);

function requiredHook() external view returns (IPostDispatchHook);

function latestDispatchedId() external view returns (bytes32);

function dispatch(
Expand Down
14 changes: 2 additions & 12 deletions solidity/contracts/test/TestSendReceiver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {IMailbox} from "../interfaces/IMailbox.sol";
import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol";
import {IInterchainSecurityModule, ISpecifiesInterchainSecurityModule} from "../interfaces/IInterchainSecurityModule.sol";

import {StandardHookMetadata} from "../hooks/libs/StandardHookMetadata.sol";
import {MailboxClient} from "../client/MailboxClient.sol";

contract TestSendReceiver is IMessageRecipient {
Expand All @@ -24,16 +23,11 @@ contract TestSendReceiver is IMessageRecipient {
uint32 _destinationDomain,
bytes calldata _messageBody
) external payable {
bytes memory hookMetadata = StandardHookMetadata.formatMetadata(
HANDLE_GAS_AMOUNT,
msg.sender
);
// TODO: handle topping up?
_mailbox.dispatch{value: msg.value}(
_destinationDomain,
address(this).addressToBytes32(),
_messageBody,
hookMetadata
_messageBody
);
}

Expand All @@ -43,16 +37,12 @@ contract TestSendReceiver is IMessageRecipient {
bytes calldata _messageBody,
IPostDispatchHook hook
) external payable {
bytes memory hookMetadata = StandardHookMetadata.formatMetadata(
HANDLE_GAS_AMOUNT,
msg.sender
);
// TODO: handle topping up?
_mailbox.dispatch{value: msg.value}(
_destinationDomain,
address(this).addressToBytes32(),
_messageBody,
hookMetadata,
bytes(""),
hook
);
}
Expand Down
7 changes: 1 addition & 6 deletions solidity/test/hooks/StaticProtocolFee.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,7 @@ contract StaticProtocolFeeTest is Test {
uint256 feeRequired,
uint256 feeSent
) public {
bytes memory metadata = StandardHookMetadata.formatMetadata(
0,
0,
bob,
""
);
bytes memory metadata = StandardHookMetadata.overrideRefundAddress(bob);

feeRequired = bound(feeRequired, 1, fees.MAX_PROTOCOL_FEE());
feeSent = bound(feeSent, feeRequired, 10 * feeRequired);
Expand Down
14 changes: 4 additions & 10 deletions solidity/test/igps/InterchainGasPaymaster.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -410,11 +410,8 @@ contract InterchainGasPaymasterTest is Test {
TEST_GAS_PRICE
);

bytes memory metadata = StandardHookMetadata.formatMetadata(
0,
uint256(testGasLimit), // gas limit
testRefundAddress, // refund address,
bytes("")
bytes memory metadata = StandardHookMetadata.overrideGasLimit(
uint256(testGasLimit)
);
// 150 * (300_000 + 123_000) = 45_000_000
assertEq(igp.quoteDispatch(metadata, testEncodedMessage), 63_450_000);
Expand Down Expand Up @@ -524,11 +521,8 @@ contract InterchainGasPaymasterTest is Test {
igp.destinationGasLimit(testDestinationDomain, testGasLimit)
);

bytes memory metadata = StandardHookMetadata.formatMetadata(
0,
uint256(testGasLimit), // gas limit
testRefundAddress, // refund address
bytes("")
bytes memory metadata = StandardHookMetadata.overrideGasLimit(
uint256(testGasLimit)
);
bytes memory message = _encodeTestMessage();
igp.postDispatch{value: _quote}(metadata, message);
Expand Down
10 changes: 3 additions & 7 deletions solidity/test/isms/OPStackIsm.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ contract OPStackIsmTest is Test {
bytes internal testMessage =
abi.encodePacked("Hello from the other chain!");
bytes internal testMetadata =
StandardHookMetadata.formatMetadata(0, 0, address(this), "");
StandardHookMetadata.overrideRefundAddress(address(this));

bytes internal encodedMessage;
bytes32 internal messageId;
Expand Down Expand Up @@ -195,12 +195,8 @@ contract OPStackIsmTest is Test {
vm.selectFork(mainnetFork);

vm.deal(address(this), uint256(2 ** 255 + 1));
bytes memory excessValueMetadata = StandardHookMetadata.formatMetadata(
uint256(2 ** 255 + 1),
DEFAULT_GAS_LIMIT,
address(this),
""
);
bytes memory excessValueMetadata = StandardHookMetadata
.overrideMsgValue(uint256(2 ** 255 + 1));

l1Mailbox.updateLatestDispatchedId(messageId);
vm.expectRevert("OPStackHook: msgValue must be less than 2 ** 255");
Expand Down
3 changes: 1 addition & 2 deletions typescript/helloworld/contracts/HelloWorld.sol
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,7 @@ contract HelloWorld is Router {
function _metadata(
uint32 /*_destinationDomain*/
) internal view override returns (bytes memory) {
return
StandardHookMetadata.formatMetadata(HANDLE_GAS_AMOUNT, msg.sender);
return StandardHookMetadata.overrideGasLimit(HANDLE_GAS_AMOUNT);
}

/**
Expand Down

0 comments on commit 83335b4

Please sign in to comment.