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

Integrating IGP as a hook #2600

Closed
wants to merge 19 commits into from
Closed
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
5 changes: 3 additions & 2 deletions solidity/contracts/Mailbox.sol
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ contract Mailbox is IMailbox, Versioned, Ownable {
_destinationDomain,
_recipientAddress,
_messageBody,
defaultHook,
bytes("")
);
}
Expand Down Expand Up @@ -134,8 +135,8 @@ contract Mailbox is IMailbox, Versioned, Ownable {
bytes32 recipientAddress,
bytes calldata messageBody,
IPostDispatchHook hook,
bytes calldata metadata
) public returns (bytes32) {
bytes memory metadata
) public payable returns (bytes32) {
// Format the message into packed bytes.
bytes memory message = Message.formatMessage(
VERSION,
Expand Down
4 changes: 4 additions & 0 deletions solidity/contracts/client/MailboxClient.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@ import {IMailbox} from "../interfaces/IMailbox.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";

abstract contract MailboxClient {
/// @notice keeping mailbox immutable for maintaining sync
IMailbox immutable mailbox;
/// @notice default hook for authorizing dispatch hook calls
address public defaultHook;

constructor(address _mailbox) {
require(Address.isContract(_mailbox), "!contract");
mailbox = IMailbox(_mailbox);
// defaultHook = mailbox.defaultHook();
}

// ============ Modifiers ============
Expand Down
101 changes: 0 additions & 101 deletions solidity/contracts/hooks/AbstractBridgeHook.sol

This file was deleted.

4 changes: 2 additions & 2 deletions solidity/contracts/hooks/AbstractHook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ abstract contract AbstractHook is MailboxClient, IPostDispatchHook {
payable
override
onlyMailbox
returns (IPostDispatchHook)
returns (address[] memory)
{
return _postDispatch(metadata, message);
}

function _postDispatch(bytes calldata metadata, bytes calldata message)
internal
virtual
returns (IPostDispatchHook);
returns (address[] memory);
}
9 changes: 4 additions & 5 deletions solidity/contracts/hooks/AbstractMessageIdAuthHook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {Address} from "@openzeppelin/contracts/utils/Address.sol";
/**
* @title AbstractMessageIdAuthHook
* @notice Message hook to inform an Abstract Message ID ISM of messages published through
* the native OPStack bridge.
* the third-party bridge.
* @dev V3 WIP
*/
abstract contract AbstractMessageIdAuthHook is AbstractHook {
Expand Down Expand Up @@ -66,7 +66,7 @@ abstract contract AbstractMessageIdAuthHook is AbstractHook {
function _postDispatch(bytes calldata metadata, bytes calldata message)
internal
override
returns (IPostDispatchHook)
returns (address[] memory)
{
require(
message.destination() == destinationDomain,
Expand All @@ -79,8 +79,7 @@ abstract contract AbstractMessageIdAuthHook is AbstractHook {
);
_sendMessageId(metadata, payload);

// no next post-dispatch hook
// TODO: consider configuring?
return IPostDispatchHook(address(0));
// leaf hook
return new address[](0);
}
}
16 changes: 8 additions & 8 deletions solidity/contracts/hooks/DomainRoutingHook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ contract DomainRoutingHook is AbstractHook, Ownable {
hooks[destination] = IPostDispatchHook(hook);
}

function _postDispatch(bytes calldata metadata, bytes calldata message)
internal
override
{
hooks[message.destination()].postDispatch{value: msg.value}(
metadata,
message
);
function _postDispatch(
bytes calldata, /*metadata*/
bytes calldata message
) internal view override returns (address[] memory) {
// check metadata
address[] memory result = new address[](1);
result[0] = address(hooks[message.destination()]);
return result;
}
}
4 changes: 3 additions & 1 deletion solidity/contracts/hooks/MerkleTreeHook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ contract MerkleTreeHook is AbstractHook {
function _postDispatch(
bytes calldata, /*metadata*/
bytes calldata message
) internal override {
) internal override returns (address[] memory) {
_tree.insert(message.id());

return new address[](0);
}
}
11 changes: 6 additions & 5 deletions solidity/contracts/hooks/PausableHook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol";
contract PausableHook is AbstractHook, Ownable, Pausable {
constructor(address _mailbox) AbstractHook(_mailbox) {}

function _postDispatch(bytes calldata metadata, bytes calldata message)
internal
override
whenNotPaused
{}
function _postDispatch(
bytes calldata, /*metadata*/
bytes calldata /*message*/
) internal view override whenNotPaused returns (address[] memory) {
return new address[](0);
}

function pause() external onlyOwner {
_pause();
Expand Down
69 changes: 59 additions & 10 deletions solidity/contracts/igps/InterchainGasPaymaster.sol
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.8.0;

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

// ============ Internal Imports ============
import {Message} from "../libs/Message.sol";
import {IGPHookMetadata} from "../libs/hooks/IGPHookMetadata.sol";
import {IGasOracle} from "../interfaces/IGasOracle.sol";
import {IInterchainGasPaymaster} from "../interfaces/IInterchainGasPaymaster.sol";
import {AbstractHook} from "../hooks/AbstractHook.sol";

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

/**
Expand All @@ -15,12 +32,18 @@ import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Own
contract InterchainGasPaymaster is
IInterchainGasPaymaster,
IGasOracle,
AbstractHook,
OwnableUpgradeable
{
using Address for address;
using IGPHookMetadata for bytes;
using Message for bytes;
// ============ Constants ============

/// @notice The scale of gas oracle token exchange rates.
uint256 internal constant TOKEN_EXCHANGE_RATE_SCALE = 1e10;
uint256 internal constant DECIMALS = 1e10;
/// @notice default for user call if metadata not provided
uint256 internal constant DEFAULT_GAS_USAGE = 69_420;

// ============ Public Storage ============

Expand Down Expand Up @@ -50,6 +73,10 @@ contract InterchainGasPaymaster is
address gasOracle;
}

// ============ Constructor ============

constructor(address _mailbox) AbstractHook(_mailbox) {}

// ============ External Functions ============

/**
Expand Down Expand Up @@ -80,19 +107,16 @@ contract InterchainGasPaymaster is
uint32 _destinationDomain,
uint256 _gasAmount,
address _refundAddress
) external payable override {
) public payable override {
uint256 _requiredPayment = quoteGasPayment(
_destinationDomain,
_gasAmount
);
require(
msg.value >= _requiredPayment,
"insufficient interchain gas payment"
);
require(msg.value >= _requiredPayment, "IGP: insufficient gas payment");
uint256 _overpayment = msg.value - _requiredPayment;
if (_overpayment > 0) {
(bool _success, ) = _refundAddress.call{value: _overpayment}("");
require(_success, "Interchain gas payment refund failed");
require(_success, "IGP: refund failed");
}

emit GasPayment(_messageId, _gasAmount, _requiredPayment);
Expand Down Expand Up @@ -155,9 +179,7 @@ contract InterchainGasPaymaster is
uint256 _destinationGasCost = _gasAmount * uint256(_gasPrice);

// Convert to the local native token.
return
(_destinationGasCost * _tokenExchangeRate) /
TOKEN_EXCHANGE_RATE_SCALE;
return (_destinationGasCost * _tokenExchangeRate) / DECIMALS;
}

/**
Expand All @@ -181,6 +203,33 @@ contract InterchainGasPaymaster is

// ============ Internal Functions ============

function _postDispatch(bytes calldata _metadata, bytes calldata _message)
internal
override
returns (address[] memory)
{
if (_metadata.length == 0) {
payForGas(
_message.id(),
_message.destination(),
DEFAULT_GAS_USAGE,
_message.senderAddress()
);
} else {
address refundAddress = _metadata.refundAddress();
if (refundAddress != address(0))
refundAddress = _message.senderAddress();
payForGas(
_message.id(),
_message.destination(),
_metadata.gasLimit(),
refundAddress
);
}

return new address[](0);
}

/**
* @notice Sets the beneficiary.
* @param _beneficiary The new beneficiary.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ interface IPostDispatchHook {
function postDispatch(bytes calldata metadata, bytes calldata message)
external
payable
returns (IPostDispatchHook next);
returns (address[] memory next);
}
Loading
Loading