Unify overheardIgp and igp (#2766)
### Description - v3 uses the OverheadIgp as the default igp and removing an "inner" igp makes it simpler to deploy and interact with - `InterchainGasPaymaster` has a `setDestinationGasConfigs` which sets it the overhead and the oracle. - the gas overhead gets added it directly to the specified gasAmount. - Downstream changes to the `typescript/*` module in the igpConfig, checke, deployer, etc ### Drive-by changes None ### Related issues - precursor to https://github.com/hyperlane-xyz/issues/issues/623 - related to https://github.com/hyperlane-xyz/issues/issues/637 - missing changes to governor https://github.com/hyperlane-xyz/issues/issues/641 ### Backward compatibility Yes ### Testing Fuzzpull/2774/head
parent
f0a45bd6b1
commit
a60ec18237
@ -1,134 +0,0 @@ |
|||||||
// SPDX-License-Identifier: MIT OR Apache-2.0 |
|
||||||
pragma solidity >=0.8.0; |
|
||||||
|
|
||||||
// ============ Internal Imports ============ |
|
||||||
import {IInterchainGasPaymaster} from "../../interfaces/IInterchainGasPaymaster.sol"; |
|
||||||
|
|
||||||
// ============ External Imports ============ |
|
||||||
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; |
|
||||||
|
|
||||||
/** |
|
||||||
* @notice An IGP that adds configured gas overheads to gas amounts and forwards |
|
||||||
* calls to an "inner" IGP. |
|
||||||
* @dev The intended use of this contract is to store overhead gas amounts for destination |
|
||||||
* domains, e.g. Mailbox and/or ISM gas usage, such that users of this IGP are only required |
|
||||||
* to specify the gas amount used by their own applications. |
|
||||||
*/ |
|
||||||
contract OverheadIgp is IInterchainGasPaymaster, Ownable { |
|
||||||
// ============ Constants ============ |
|
||||||
|
|
||||||
/// @notice The IGP that is called when paying for or quoting gas |
|
||||||
/// after applying overhead gas amounts. |
|
||||||
IInterchainGasPaymaster public immutable innerIgp; |
|
||||||
|
|
||||||
// ============ Public Storage ============ |
|
||||||
|
|
||||||
/// @notice Destination domain => overhead gas amount on that domain. |
|
||||||
mapping(uint32 => uint256) public destinationGasOverhead; |
|
||||||
|
|
||||||
// ============ Events ============ |
|
||||||
|
|
||||||
/** |
|
||||||
* @notice Emitted when an entry in the destinationGasOverhead mapping is set. |
|
||||||
* @param domain The destination domain. |
|
||||||
* @param gasOverhead The gas overhead amount on that domain. |
|
||||||
*/ |
|
||||||
event DestinationGasOverheadSet(uint32 indexed domain, uint256 gasOverhead); |
|
||||||
|
|
||||||
struct DomainConfig { |
|
||||||
uint32 domain; |
|
||||||
uint256 gasOverhead; |
|
||||||
} |
|
||||||
|
|
||||||
// ============ Constructor ============ |
|
||||||
|
|
||||||
constructor(address _innerIgp) { |
|
||||||
innerIgp = IInterchainGasPaymaster(_innerIgp); |
|
||||||
} |
|
||||||
|
|
||||||
// ============ External Functions ============ |
|
||||||
|
|
||||||
/** |
|
||||||
* @notice Adds the stored destinationGasOverhead to the _gasAmount and forwards the |
|
||||||
* call to the innerIgp's `payForGas` function. |
|
||||||
* @param _messageId The ID of the message to pay for. |
|
||||||
* @param _destinationDomain The domain of the message's destination chain. |
|
||||||
* @param _gasAmount The amount of destination gas to pay for. This should not |
|
||||||
* consider any gas that is accounted for in the stored destinationGasOverhead. |
|
||||||
* @param _refundAddress The address to refund any overpayment to. |
|
||||||
*/ |
|
||||||
function payForGas( |
|
||||||
bytes32 _messageId, |
|
||||||
uint32 _destinationDomain, |
|
||||||
uint256 _gasAmount, |
|
||||||
address _refundAddress |
|
||||||
) external payable { |
|
||||||
innerIgp.payForGas{value: msg.value}( |
|
||||||
_messageId, |
|
||||||
_destinationDomain, |
|
||||||
destinationGasAmount(_destinationDomain, _gasAmount), |
|
||||||
_refundAddress |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @notice Sets destination gas overheads for multiple domains. |
|
||||||
* @dev Only callable by the owner. |
|
||||||
* @param configs A list of destination domains and gas overheads. |
|
||||||
*/ |
|
||||||
function setDestinationGasOverheads(DomainConfig[] calldata configs) |
|
||||||
external |
|
||||||
onlyOwner |
|
||||||
{ |
|
||||||
for (uint256 i; i < configs.length; i++) { |
|
||||||
_setDestinationGasOverhead(configs[i]); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// ============ Public Functions ============ |
|
||||||
|
|
||||||
/** |
|
||||||
* @notice Adds the stored destinationGasOverhead to the _gasAmount and forwards the |
|
||||||
* call to the innerIgp's `quoteGasPayment` function. |
|
||||||
* @param _destinationDomain The domain of the message's destination chain. |
|
||||||
* @param _gasAmount The amount of destination gas to pay for. This should not |
|
||||||
* consider any gas that is accounted for in the stored destinationGasOverhead. |
|
||||||
* @return The amount of native tokens required to pay for interchain gas. |
|
||||||
*/ |
|
||||||
function quoteGasPayment(uint32 _destinationDomain, uint256 _gasAmount) |
|
||||||
public |
|
||||||
view |
|
||||||
returns (uint256) |
|
||||||
{ |
|
||||||
return |
|
||||||
innerIgp.quoteGasPayment( |
|
||||||
_destinationDomain, |
|
||||||
destinationGasAmount(_destinationDomain, _gasAmount) |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @notice Returns the stored destinationGasOverhead added to the _gasAmount. |
|
||||||
* @dev If there is no stored destinationGasOverhead, 0 is used. |
|
||||||
* @param _destinationDomain The domain of the message's destination chain. |
|
||||||
* @param _gasAmount The amount of destination gas to pay for. This should not |
|
||||||
* consider any gas that is accounted for in the stored destinationGasOverhead. |
|
||||||
* @return The stored destinationGasOverhead added to the _gasAmount. |
|
||||||
*/ |
|
||||||
function destinationGasAmount(uint32 _destinationDomain, uint256 _gasAmount) |
|
||||||
public |
|
||||||
view |
|
||||||
returns (uint256) |
|
||||||
{ |
|
||||||
return destinationGasOverhead[_destinationDomain] + _gasAmount; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @notice Sets the destination gas overhead for a single domain. |
|
||||||
* @param config The destination domain and gas overhead. |
|
||||||
*/ |
|
||||||
function _setDestinationGasOverhead(DomainConfig calldata config) internal { |
|
||||||
destinationGasOverhead[config.domain] = config.gasOverhead; |
|
||||||
emit DestinationGasOverheadSet(config.domain, config.gasOverhead); |
|
||||||
} |
|
||||||
} |
|
@ -1,146 +0,0 @@ |
|||||||
// SPDX-License-Identifier: Apache-2.0 |
|
||||||
pragma solidity ^0.8.13; |
|
||||||
|
|
||||||
import {Test} from "forge-std/Test.sol"; |
|
||||||
import {OverheadIgp} from "../../contracts/hooks/igp/OverheadIgp.sol"; |
|
||||||
import {TestInterchainGasPaymaster} from "../../contracts/test/TestInterchainGasPaymaster.sol"; |
|
||||||
|
|
||||||
contract OverheadIgpTest is Test { |
|
||||||
OverheadIgp igp; |
|
||||||
|
|
||||||
TestInterchainGasPaymaster innerIgp; |
|
||||||
|
|
||||||
bytes32 constant testMessageId = |
|
||||||
bytes32( |
|
||||||
0xf00000000000000000000000000000000000000000000000000000000000000f |
|
||||||
); |
|
||||||
uint32 constant testDestinationDomain = 1234; |
|
||||||
uint256 constant testGasOverhead = 123000; |
|
||||||
uint256 constant testGasAmount = 50000; |
|
||||||
|
|
||||||
address constant nonOwner = 0xCAfEcAfeCAfECaFeCaFecaFecaFECafECafeCaFe; |
|
||||||
|
|
||||||
event InnerIgpSet(address innerIgp); |
|
||||||
event DestinationGasOverheadSet(uint32 indexed domain, uint256 gasOverhead); |
|
||||||
|
|
||||||
function setUp() public { |
|
||||||
innerIgp = new TestInterchainGasPaymaster(); |
|
||||||
igp = new OverheadIgp(address(innerIgp)); |
|
||||||
} |
|
||||||
|
|
||||||
function testInnerIgpSet() public { |
|
||||||
assertEq(address(igp.innerIgp()), address(innerIgp)); |
|
||||||
} |
|
||||||
|
|
||||||
function testPayForGas() public { |
|
||||||
setTestDestinationGasOverhead(); |
|
||||||
|
|
||||||
uint256 testPayment = 123456789; |
|
||||||
|
|
||||||
vm.expectCall( |
|
||||||
address(innerIgp), |
|
||||||
testPayment, |
|
||||||
abi.encodeCall( |
|
||||||
innerIgp.payForGas, |
|
||||||
( |
|
||||||
testMessageId, |
|
||||||
testDestinationDomain, |
|
||||||
testGasOverhead + testGasAmount, |
|
||||||
msg.sender |
|
||||||
) |
|
||||||
) |
|
||||||
); |
|
||||||
|
|
||||||
igp.payForGas{value: testPayment}( |
|
||||||
testMessageId, |
|
||||||
testDestinationDomain, |
|
||||||
testGasAmount, |
|
||||||
msg.sender |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
function testQuoteGasPayment() public { |
|
||||||
setTestDestinationGasOverhead(); |
|
||||||
|
|
||||||
vm.expectCall( |
|
||||||
address(innerIgp), |
|
||||||
abi.encodeCall( |
|
||||||
innerIgp.quoteGasPayment, |
|
||||||
(testDestinationDomain, testGasOverhead + testGasAmount) |
|
||||||
) |
|
||||||
); |
|
||||||
|
|
||||||
igp.quoteGasPayment(testDestinationDomain, testGasAmount); |
|
||||||
} |
|
||||||
|
|
||||||
function testDestinationGasAmount() public { |
|
||||||
setTestDestinationGasOverhead(); |
|
||||||
|
|
||||||
assertEq( |
|
||||||
igp.destinationGasAmount(testDestinationDomain, testGasAmount), |
|
||||||
testGasOverhead + testGasAmount |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
// Test that it doesn't revert, and just doesn't add any value to the |
|
||||||
// provided gas amount |
|
||||||
function testDestinationGasAmountWhenOverheadNotSet() public { |
|
||||||
assertEq( |
|
||||||
igp.destinationGasAmount(testDestinationDomain, testGasAmount), |
|
||||||
testGasAmount |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
function testSetDestinationGasAmounts() public { |
|
||||||
OverheadIgp.DomainConfig[] |
|
||||||
memory configs = new OverheadIgp.DomainConfig[](2); |
|
||||||
configs[0] = OverheadIgp.DomainConfig( |
|
||||||
testDestinationDomain, |
|
||||||
testGasOverhead |
|
||||||
); |
|
||||||
configs[1] = OverheadIgp.DomainConfig(4321, 432100); |
|
||||||
|
|
||||||
// Topic 0 = event signature |
|
||||||
// Topic 1 = indexed domain |
|
||||||
// Topic 2 = not set |
|
||||||
// Data = gas amount |
|
||||||
vm.expectEmit(true, true, false, true); |
|
||||||
emit DestinationGasOverheadSet( |
|
||||||
configs[0].domain, |
|
||||||
configs[0].gasOverhead |
|
||||||
); |
|
||||||
vm.expectEmit(true, true, false, true); |
|
||||||
emit DestinationGasOverheadSet( |
|
||||||
configs[1].domain, |
|
||||||
configs[1].gasOverhead |
|
||||||
); |
|
||||||
|
|
||||||
igp.setDestinationGasOverheads(configs); |
|
||||||
} |
|
||||||
|
|
||||||
function testSetDestinationGasAmountsNotOwner() public { |
|
||||||
OverheadIgp.DomainConfig[] |
|
||||||
memory configs = new OverheadIgp.DomainConfig[](2); |
|
||||||
configs[0] = OverheadIgp.DomainConfig( |
|
||||||
testDestinationDomain, |
|
||||||
testGasOverhead |
|
||||||
); |
|
||||||
configs[1] = OverheadIgp.DomainConfig(4321, 432100); |
|
||||||
|
|
||||||
vm.expectRevert("Ownable: caller is not the owner"); |
|
||||||
vm.prank(nonOwner); |
|
||||||
igp.setDestinationGasOverheads(configs); |
|
||||||
} |
|
||||||
|
|
||||||
// ============ Helper Functions ============ |
|
||||||
|
|
||||||
function setTestDestinationGasOverhead() internal { |
|
||||||
OverheadIgp.DomainConfig[] |
|
||||||
memory configs = new OverheadIgp.DomainConfig[](1); |
|
||||||
configs[0] = OverheadIgp.DomainConfig( |
|
||||||
testDestinationDomain, |
|
||||||
testGasOverhead |
|
||||||
); |
|
||||||
igp.setDestinationGasOverheads(configs); |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue