@hyperlane-xyz/core 1.0.0 → 1.1.0-beta0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/contracts/Mailbox.sol +0 -1
  2. package/contracts/OwnableMulticall.sol +6 -37
  3. package/contracts/ValidatorAnnounce.sol +117 -0
  4. package/contracts/{InterchainGasPaymaster.sol → igps/InterchainGasPaymaster.sol} +3 -3
  5. package/contracts/igps/OverheadIgp.sol +133 -0
  6. package/contracts/libs/Call.sol +54 -0
  7. package/contracts/libs/ValidatorAnnouncements.sol +35 -0
  8. package/contracts/middleware/InterchainAccountRouter.sol +7 -6
  9. package/contracts/middleware/InterchainQueryRouter.sol +17 -14
  10. package/contracts/mock/MockHyperlaneEnvironment.sol +1 -1
  11. package/contracts/mock/MockMailbox.sol +4 -4
  12. package/contracts/test/LightTestRecipient.sol +12 -0
  13. package/contracts/test/TestQuery.sol +3 -6
  14. package/contracts/test/TestQuerySender.sol +48 -19
  15. package/contracts/test/TestRecipient.sol +1 -1
  16. package/dist/contracts/OwnableMulticall.d.ts +16 -14
  17. package/dist/contracts/OwnableMulticall.d.ts.map +1 -1
  18. package/dist/contracts/ValidatorAnnounce.d.ts +98 -0
  19. package/dist/contracts/ValidatorAnnounce.d.ts.map +1 -0
  20. package/dist/contracts/ValidatorAnnounce.js +4 -0
  21. package/dist/contracts/ValidatorAnnounce.js.map +1 -0
  22. package/dist/contracts/{InterchainGasPaymaster.d.ts → igps/InterchainGasPaymaster.d.ts} +1 -1
  23. package/dist/contracts/igps/InterchainGasPaymaster.d.ts.map +1 -0
  24. package/dist/contracts/{InterchainGasPaymaster.js → igps/InterchainGasPaymaster.js} +0 -0
  25. package/dist/contracts/igps/InterchainGasPaymaster.js.map +1 -0
  26. package/dist/contracts/igps/OverheadIgp.d.ts +177 -0
  27. package/dist/contracts/igps/OverheadIgp.d.ts.map +1 -0
  28. package/dist/contracts/igps/OverheadIgp.js +4 -0
  29. package/dist/contracts/igps/OverheadIgp.js.map +1 -0
  30. package/dist/contracts/igps/index.d.ts +3 -0
  31. package/dist/contracts/igps/index.d.ts.map +1 -0
  32. package/dist/contracts/igps/index.js +3 -0
  33. package/dist/contracts/igps/index.js.map +1 -0
  34. package/dist/contracts/index.d.ts +3 -1
  35. package/dist/contracts/index.d.ts.map +1 -1
  36. package/dist/contracts/middleware/InterchainAccountRouter.d.ts +16 -14
  37. package/dist/contracts/middleware/InterchainAccountRouter.d.ts.map +1 -1
  38. package/dist/contracts/middleware/InterchainQueryRouter.d.ts +22 -20
  39. package/dist/contracts/middleware/InterchainQueryRouter.d.ts.map +1 -1
  40. package/dist/contracts/mock/MockMailbox.d.ts +17 -17
  41. package/dist/contracts/mock/MockMailbox.d.ts.map +1 -1
  42. package/dist/contracts/test/LightTestRecipient.d.ts +155 -0
  43. package/dist/contracts/test/LightTestRecipient.d.ts.map +1 -0
  44. package/dist/contracts/test/LightTestRecipient.js +4 -0
  45. package/dist/contracts/test/LightTestRecipient.js.map +1 -0
  46. package/dist/contracts/test/TestQuerySender.d.ts +29 -38
  47. package/dist/contracts/test/TestQuerySender.d.ts.map +1 -1
  48. package/dist/contracts/test/index.d.ts +1 -0
  49. package/dist/contracts/test/index.d.ts.map +1 -1
  50. package/dist/factories/contracts/Mailbox__factory.d.ts +1 -1
  51. package/dist/factories/contracts/Mailbox__factory.js +1 -1
  52. package/dist/factories/contracts/OwnableMulticall__factory.d.ts +1 -1
  53. package/dist/factories/contracts/OwnableMulticall__factory.d.ts.map +1 -1
  54. package/dist/factories/contracts/OwnableMulticall__factory.js +2 -2
  55. package/dist/factories/contracts/OwnableMulticall__factory.js.map +1 -1
  56. package/dist/factories/contracts/ValidatorAnnounce__factory.d.ts +59 -0
  57. package/dist/factories/contracts/ValidatorAnnounce__factory.d.ts.map +1 -0
  58. package/dist/factories/contracts/ValidatorAnnounce__factory.js +158 -0
  59. package/dist/factories/contracts/ValidatorAnnounce__factory.js.map +1 -0
  60. package/dist/factories/contracts/{InterchainGasPaymaster__factory.d.ts → igps/InterchainGasPaymaster__factory.d.ts} +2 -2
  61. package/dist/factories/contracts/igps/InterchainGasPaymaster__factory.d.ts.map +1 -0
  62. package/dist/factories/contracts/{InterchainGasPaymaster__factory.js → igps/InterchainGasPaymaster__factory.js} +1 -1
  63. package/dist/factories/contracts/igps/InterchainGasPaymaster__factory.js.map +1 -0
  64. package/dist/factories/contracts/igps/OverheadIgp__factory.d.ts +75 -0
  65. package/dist/factories/contracts/igps/OverheadIgp__factory.d.ts.map +1 -0
  66. package/dist/factories/contracts/igps/OverheadIgp__factory.js +256 -0
  67. package/dist/factories/contracts/igps/OverheadIgp__factory.js.map +1 -0
  68. package/dist/factories/contracts/igps/index.d.ts +3 -0
  69. package/dist/factories/contracts/igps/index.d.ts.map +1 -0
  70. package/dist/factories/contracts/igps/index.js +11 -0
  71. package/dist/factories/contracts/igps/index.js.map +1 -0
  72. package/dist/factories/contracts/index.d.ts +2 -1
  73. package/dist/factories/contracts/index.d.ts.map +1 -1
  74. package/dist/factories/contracts/index.js +4 -3
  75. package/dist/factories/contracts/index.js.map +1 -1
  76. package/dist/factories/contracts/middleware/InterchainAccountRouter__factory.d.ts +1 -1
  77. package/dist/factories/contracts/middleware/InterchainAccountRouter__factory.d.ts.map +1 -1
  78. package/dist/factories/contracts/middleware/InterchainAccountRouter__factory.js +2 -2
  79. package/dist/factories/contracts/middleware/InterchainAccountRouter__factory.js.map +1 -1
  80. package/dist/factories/contracts/middleware/InterchainQueryRouter__factory.d.ts +1 -1
  81. package/dist/factories/contracts/middleware/InterchainQueryRouter__factory.d.ts.map +1 -1
  82. package/dist/factories/contracts/middleware/InterchainQueryRouter__factory.js +3 -3
  83. package/dist/factories/contracts/middleware/InterchainQueryRouter__factory.js.map +1 -1
  84. package/dist/factories/contracts/middleware/liquidity-layer/LiquidityLayerRouter__factory.d.ts +1 -1
  85. package/dist/factories/contracts/middleware/liquidity-layer/LiquidityLayerRouter__factory.js +1 -1
  86. package/dist/factories/contracts/mock/MockHyperlaneEnvironment__factory.d.ts +1 -1
  87. package/dist/factories/contracts/mock/MockHyperlaneEnvironment__factory.d.ts.map +1 -1
  88. package/dist/factories/contracts/mock/MockHyperlaneEnvironment__factory.js +1 -1
  89. package/dist/factories/contracts/mock/MockHyperlaneEnvironment__factory.js.map +1 -1
  90. package/dist/factories/contracts/mock/MockMailbox__factory.d.ts +1 -1
  91. package/dist/factories/contracts/mock/MockMailbox__factory.d.ts.map +1 -1
  92. package/dist/factories/contracts/mock/MockMailbox__factory.js +27 -27
  93. package/dist/factories/contracts/mock/MockMailbox__factory.js.map +1 -1
  94. package/dist/factories/contracts/test/LightTestRecipient__factory.d.ts +55 -0
  95. package/dist/factories/contracts/test/LightTestRecipient__factory.d.ts.map +1 -0
  96. package/dist/factories/contracts/test/LightTestRecipient__factory.js +210 -0
  97. package/dist/factories/contracts/test/LightTestRecipient__factory.js.map +1 -0
  98. package/dist/factories/contracts/test/TestMailbox__factory.d.ts +1 -1
  99. package/dist/factories/contracts/test/TestMailbox__factory.js +1 -1
  100. package/dist/factories/contracts/test/TestQuerySender__factory.d.ts +1 -1
  101. package/dist/factories/contracts/test/TestQuerySender__factory.d.ts.map +1 -1
  102. package/dist/factories/contracts/test/TestQuerySender__factory.js +24 -17
  103. package/dist/factories/contracts/test/TestQuerySender__factory.js.map +1 -1
  104. package/dist/factories/contracts/test/TestQuery__factory.d.ts +1 -1
  105. package/dist/factories/contracts/test/TestQuery__factory.d.ts.map +1 -1
  106. package/dist/factories/contracts/test/TestQuery__factory.js +1 -1
  107. package/dist/factories/contracts/test/TestQuery__factory.js.map +1 -1
  108. package/dist/factories/contracts/test/TestRecipient__factory.d.ts +1 -1
  109. package/dist/factories/contracts/test/TestRecipient__factory.js +1 -1
  110. package/dist/factories/contracts/test/index.d.ts +1 -0
  111. package/dist/factories/contracts/test/index.d.ts.map +1 -1
  112. package/dist/factories/contracts/test/index.js +3 -1
  113. package/dist/factories/contracts/test/index.js.map +1 -1
  114. package/dist/factories/interfaces/IInterchainAccountRouter__factory.js +1 -1
  115. package/dist/factories/interfaces/IInterchainAccountRouter__factory.js.map +1 -1
  116. package/dist/factories/interfaces/IInterchainQueryRouter__factory.js +2 -2
  117. package/dist/factories/interfaces/IInterchainQueryRouter__factory.js.map +1 -1
  118. package/dist/factories/interfaces/IValidatorAnnounce__factory.d.ts +23 -0
  119. package/dist/factories/interfaces/IValidatorAnnounce__factory.d.ts.map +1 -0
  120. package/dist/factories/interfaces/IValidatorAnnounce__factory.js +105 -0
  121. package/dist/factories/interfaces/IValidatorAnnounce__factory.js.map +1 -0
  122. package/dist/factories/interfaces/index.d.ts +1 -0
  123. package/dist/factories/interfaces/index.d.ts.map +1 -1
  124. package/dist/factories/interfaces/index.js +3 -1
  125. package/dist/factories/interfaces/index.js.map +1 -1
  126. package/dist/index.d.ts +10 -2
  127. package/dist/index.d.ts.map +1 -1
  128. package/dist/index.js +11 -3
  129. package/dist/index.js.map +1 -1
  130. package/dist/interfaces/IInterchainAccountRouter.d.ts +16 -14
  131. package/dist/interfaces/IInterchainAccountRouter.d.ts.map +1 -1
  132. package/dist/interfaces/IInterchainQueryRouter.d.ts +22 -20
  133. package/dist/interfaces/IInterchainQueryRouter.d.ts.map +1 -1
  134. package/dist/interfaces/IValidatorAnnounce.d.ts +83 -0
  135. package/dist/interfaces/IValidatorAnnounce.d.ts.map +1 -0
  136. package/dist/interfaces/IValidatorAnnounce.js +4 -0
  137. package/dist/interfaces/IValidatorAnnounce.js.map +1 -0
  138. package/dist/interfaces/index.d.ts +1 -0
  139. package/dist/interfaces/index.d.ts.map +1 -1
  140. package/interfaces/IInterchainAccountRouter.sol +2 -2
  141. package/interfaces/IInterchainQueryRouter.sol +3 -3
  142. package/interfaces/ILiquidityLayerRouter.sol +0 -2
  143. package/interfaces/IValidatorAnnounce.sol +36 -0
  144. package/package.json +5 -4
  145. package/contracts/Call.sol +0 -7
  146. package/dist/contracts/InterchainGasPaymaster.d.ts.map +0 -1
  147. package/dist/contracts/InterchainGasPaymaster.js.map +0 -1
  148. package/dist/factories/contracts/InterchainGasPaymaster__factory.d.ts.map +0 -1
  149. package/dist/factories/contracts/InterchainGasPaymaster__factory.js.map +0 -1
@@ -107,7 +107,6 @@ contract Mailbox is
107
107
 
108
108
  // ============ Constructor ============
109
109
 
110
- // solhint-disable-next-line no-empty-blocks
111
110
  constructor(uint32 _localDomain) {
112
111
  localDomain = _localDomain;
113
112
  }
@@ -4,38 +4,16 @@ pragma solidity ^0.8.13;
4
4
  // ============ External Imports ============
5
5
 
6
6
  import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
7
- import {Call} from "./Call.sol";
8
-
9
- function _call(Call[] memory calls, bytes[] memory callbacks)
10
- returns (bytes[] memory resolveCalls)
11
- {
12
- resolveCalls = new bytes[](callbacks.length);
13
- for (uint256 i = 0; i < calls.length; i++) {
14
- (bool success, bytes memory returnData) = calls[i].to.call(
15
- calls[i].data
16
- );
17
- require(success, "Multicall: call failed");
18
- resolveCalls[i] = bytes.concat(callbacks[i], returnData);
19
- }
20
- }
21
-
22
- // TODO: deduplicate
23
- function _proxyCallBatch(address to, bytes[] memory calls) {
24
- for (uint256 i = 0; i < calls.length; i += 1) {
25
- (bool success, bytes memory returnData) = to.call(calls[i]);
26
- if (!success) {
27
- assembly {
28
- revert(add(returnData, 32), returnData)
29
- }
30
- }
31
- }
32
- }
7
+ import {Address} from "@openzeppelin/contracts/utils/Address.sol";
8
+ import {CallLib} from "./libs/Call.sol";
33
9
 
34
10
  /*
35
11
  * @title OwnableMulticall
36
12
  * @dev Allows only only address to execute calls to other contracts
37
13
  */
38
14
  contract OwnableMulticall is OwnableUpgradeable {
15
+ using CallLib for CallLib.Call[];
16
+
39
17
  constructor() {
40
18
  _transferOwnership(msg.sender);
41
19
  }
@@ -44,16 +22,7 @@ contract OwnableMulticall is OwnableUpgradeable {
44
22
  __Ownable_init();
45
23
  }
46
24
 
47
- function proxyCalls(Call[] calldata calls) external onlyOwner {
48
- for (uint256 i = 0; i < calls.length; i += 1) {
49
- (bool success, bytes memory returnData) = calls[i].to.call(
50
- calls[i].data
51
- );
52
- if (!success) {
53
- assembly {
54
- revert(add(returnData, 32), returnData)
55
- }
56
- }
57
- }
25
+ function proxyCalls(CallLib.Call[] calldata calls) external onlyOwner {
26
+ calls._multicall();
58
27
  }
59
28
  }
@@ -0,0 +1,117 @@
1
+ // SPDX-License-Identifier: MIT OR Apache-2.0
2
+ pragma solidity >=0.8.0;
3
+
4
+ // ============ Internal Imports ============
5
+ import {IValidatorAnnounce} from "../interfaces/IValidatorAnnounce.sol";
6
+ import {IMailbox} from "../interfaces/IMailbox.sol";
7
+ import {TypeCasts} from "./libs/TypeCasts.sol";
8
+ import {ValidatorAnnouncements} from "./libs/ValidatorAnnouncements.sol";
9
+ // ============ External Imports ============
10
+ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
11
+ import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
12
+
13
+ /**
14
+ * @title ValidatorAnnounce
15
+ * @notice Stores the location(s) of validator signed checkpoints
16
+ */
17
+ contract ValidatorAnnounce is IValidatorAnnounce {
18
+ // ============ Libraries ============
19
+
20
+ using EnumerableSet for EnumerableSet.AddressSet;
21
+ using TypeCasts for address;
22
+
23
+ // ============ Constants ============
24
+
25
+ // Address of the mailbox being validated
26
+ address public immutable mailbox;
27
+ // Domain of chain on which the contract is deployed
28
+ uint32 public immutable localDomain;
29
+
30
+ // ============ Public Storage ============
31
+
32
+ // The set of validators that have announced
33
+ EnumerableSet.AddressSet private validators;
34
+ // Storage locations of validator signed checkpoints
35
+ mapping(address => string[]) private storageLocations;
36
+ // Mapping to prevent the same announcement from being registered
37
+ // multiple times.
38
+ mapping(bytes32 => bool) private replayProtection;
39
+
40
+ // ============ Events ============
41
+
42
+ /**
43
+ * @notice Emitted when a new validator announcement is made
44
+ * @param validator The address of the announcing validator
45
+ * @param storageLocation The storage location being announced
46
+ */
47
+ event ValidatorAnnouncement(
48
+ address indexed validator,
49
+ string storageLocation
50
+ );
51
+
52
+ // ============ Constructor ============
53
+
54
+ constructor(address _mailbox) {
55
+ mailbox = _mailbox;
56
+ localDomain = IMailbox(mailbox).localDomain();
57
+ }
58
+
59
+ // ============ External Functions ============
60
+
61
+ /**
62
+ * @notice Announces a validator signature storage location
63
+ * @param _storageLocation Information encoding the location of signed
64
+ * checkpoints
65
+ * @param _signature The signed validator announcement
66
+ * @return True upon success
67
+ */
68
+ function announce(
69
+ address _validator,
70
+ string calldata _storageLocation,
71
+ bytes calldata _signature
72
+ ) external returns (bool) {
73
+ // Ensure that the same storage metadata isn't being announced
74
+ // multiple times for the same validator.
75
+ bytes32 _replayId = keccak256(
76
+ abi.encodePacked(_validator, _storageLocation)
77
+ );
78
+ require(replayProtection[_replayId] == false, "replay");
79
+ replayProtection[_replayId] = true;
80
+
81
+ // Verify that the signature matches the declared validator
82
+ bytes32 _announcementDigest = ValidatorAnnouncements
83
+ .getAnnouncementDigest(mailbox, localDomain, _storageLocation);
84
+ address _signer = ECDSA.recover(_announcementDigest, _signature);
85
+ require(_signer == _validator, "!signature");
86
+
87
+ // Store the announcement
88
+ if (!validators.contains(_validator)) {
89
+ validators.add(_validator);
90
+ }
91
+ storageLocations[_validator].push(_storageLocation);
92
+ emit ValidatorAnnouncement(_validator, _storageLocation);
93
+ return true;
94
+ }
95
+
96
+ /**
97
+ * @notice Returns a list of all announced storage locations
98
+ * @param _validators The list of validators to get registrations for
99
+ * @return A list of registered storage metadata
100
+ */
101
+ function getAnnouncedStorageLocations(address[] calldata _validators)
102
+ external
103
+ view
104
+ returns (string[][] memory)
105
+ {
106
+ string[][] memory _metadata = new string[][](_validators.length);
107
+ for (uint256 i = 0; i < _validators.length; i++) {
108
+ _metadata[i] = storageLocations[_validators[i]];
109
+ }
110
+ return _metadata;
111
+ }
112
+
113
+ /// @notice Returns a list of validators that have made announcements
114
+ function getAnnouncedValidators() external view returns (address[] memory) {
115
+ return validators.values();
116
+ }
117
+ }
@@ -2,7 +2,7 @@
2
2
  pragma solidity >=0.8.0;
3
3
 
4
4
  // ============ Internal Imports ============
5
- import {IInterchainGasPaymaster} from "../interfaces/IInterchainGasPaymaster.sol";
5
+ import {IInterchainGasPaymaster} from "../../interfaces/IInterchainGasPaymaster.sol";
6
6
  // ============ External Imports ============
7
7
  import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
8
8
 
@@ -28,7 +28,6 @@ contract InterchainGasPaymaster is IInterchainGasPaymaster, OwnableUpgradeable {
28
28
 
29
29
  // ============ Constructor ============
30
30
 
31
- // solhint-disable-next-line no-empty-blocks
32
31
  constructor() {
33
32
  initialize(); // allows contract to be used without proxying
34
33
  }
@@ -42,6 +41,8 @@ contract InterchainGasPaymaster is IInterchainGasPaymaster, OwnableUpgradeable {
42
41
  /**
43
42
  * @notice Deposits msg.value as a payment for the relaying of a message
44
43
  * to its destination chain.
44
+ * @dev Overpayment will result in a refund of native tokens to the _refundAddress.
45
+ * Callers should be aware that this may present reentrancy issues.
45
46
  * @param _messageId The ID of the message to pay for.
46
47
  * @param _destinationDomain The domain of the message's destination chain.
47
48
  * @param _gasAmount The amount of destination gas to pay for. Currently unused.
@@ -64,7 +65,6 @@ contract InterchainGasPaymaster is IInterchainGasPaymaster, OwnableUpgradeable {
64
65
  uint256 _overpayment = msg.value - _requiredPayment;
65
66
  if (_overpayment > 0) {
66
67
  (bool _success, ) = _refundAddress.call{value: _overpayment}("");
67
- // TODO reconsider this?
68
68
  require(_success, "Interchain gas payment refund failed");
69
69
  }
70
70
 
@@ -0,0 +1,133 @@
1
+ // SPDX-License-Identifier: MIT OR Apache-2.0
2
+ pragma solidity >=0.8.0;
3
+
4
+ // ============ Internal Imports ============
5
+ import {IInterchainGasPaymaster} from "../../interfaces/IInterchainGasPaymaster.sol";
6
+ // ============ External Imports ============
7
+ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
8
+
9
+ /**
10
+ * @notice An IGP that adds configured gas overheads to gas amounts and forwards
11
+ * calls to an "inner" IGP.
12
+ * @dev The intended use of this contract is to store overhead gas amounts for destination
13
+ * domains, e.g. Mailbox and/or ISM gas usage, such that users of this IGP are only required
14
+ * to specify the gas amount used by their own applications.
15
+ */
16
+ contract OverheadIgp is IInterchainGasPaymaster, Ownable {
17
+ // ============ Constants ============
18
+
19
+ /// @notice The IGP that is called when paying for or quoting gas
20
+ /// after applying overhead gas amounts.
21
+ IInterchainGasPaymaster public immutable innerIgp;
22
+
23
+ // ============ Public Storage ============
24
+
25
+ /// @notice Destination domain => overhead gas amount on that domain.
26
+ mapping(uint32 => uint256) public destinationGasOverhead;
27
+
28
+ // ============ Events ============
29
+
30
+ /**
31
+ * @notice Emitted when an entry in the destinationGasOverhead mapping is set.
32
+ * @param domain The destination domain.
33
+ * @param gasOverhead The gas overhead amount on that domain.
34
+ */
35
+ event DestinationGasOverheadSet(uint32 indexed domain, uint256 gasOverhead);
36
+
37
+ struct DomainConfig {
38
+ uint32 domain;
39
+ uint256 gasOverhead;
40
+ }
41
+
42
+ // ============ Constructor ============
43
+
44
+ constructor(address _innerIgp) {
45
+ innerIgp = IInterchainGasPaymaster(_innerIgp);
46
+ }
47
+
48
+ // ============ External Functions ============
49
+
50
+ /**
51
+ * @notice Adds the stored destinationGasOverhead to the _gasAmount and forwards the
52
+ * call to the innerIgp's `payForGas` function.
53
+ * @param _messageId The ID of the message to pay for.
54
+ * @param _destinationDomain The domain of the message's destination chain.
55
+ * @param _gasAmount The amount of destination gas to pay for. This should not
56
+ * consider any gas that is accounted for in the stored destinationGasOverhead.
57
+ * @param _refundAddress The address to refund any overpayment to.
58
+ */
59
+ function payForGas(
60
+ bytes32 _messageId,
61
+ uint32 _destinationDomain,
62
+ uint256 _gasAmount,
63
+ address _refundAddress
64
+ ) external payable {
65
+ innerIgp.payForGas{value: msg.value}(
66
+ _messageId,
67
+ _destinationDomain,
68
+ destinationGasAmount(_destinationDomain, _gasAmount),
69
+ _refundAddress
70
+ );
71
+ }
72
+
73
+ /**
74
+ * @notice Sets destination gas overheads for multiple domains.
75
+ * @dev Only callable by the owner.
76
+ * @param configs A list of destination domains and gas overheads.
77
+ */
78
+ function setDestinationGasOverheads(DomainConfig[] calldata configs)
79
+ external
80
+ onlyOwner
81
+ {
82
+ for (uint256 i; i < configs.length; i++) {
83
+ _setDestinationGasOverhead(configs[i]);
84
+ }
85
+ }
86
+
87
+ // ============ Public Functions ============
88
+
89
+ /**
90
+ * @notice Adds the stored destinationGasOverhead to the _gasAmount and forwards the
91
+ * call to the innerIgp's `quoteGasPayment` function.
92
+ * @param _destinationDomain The domain of the message's destination chain.
93
+ * @param _gasAmount The amount of destination gas to pay for. This should not
94
+ * consider any gas that is accounted for in the stored destinationGasOverhead.
95
+ * @return The amount of native tokens required to pay for interchain gas.
96
+ */
97
+ function quoteGasPayment(uint32 _destinationDomain, uint256 _gasAmount)
98
+ public
99
+ view
100
+ returns (uint256)
101
+ {
102
+ return
103
+ innerIgp.quoteGasPayment(
104
+ _destinationDomain,
105
+ destinationGasAmount(_destinationDomain, _gasAmount)
106
+ );
107
+ }
108
+
109
+ /**
110
+ * @notice Returns the stored destinationGasOverhead added to the _gasAmount.
111
+ * @dev If there is no stored destinationGasOverhead, 0 is used.
112
+ * @param _destinationDomain The domain of the message's destination chain.
113
+ * @param _gasAmount The amount of destination gas to pay for. This should not
114
+ * consider any gas that is accounted for in the stored destinationGasOverhead.
115
+ * @return The stored destinationGasOverhead added to the _gasAmount.
116
+ */
117
+ function destinationGasAmount(uint32 _destinationDomain, uint256 _gasAmount)
118
+ public
119
+ view
120
+ returns (uint256)
121
+ {
122
+ return destinationGasOverhead[_destinationDomain] + _gasAmount;
123
+ }
124
+
125
+ /**
126
+ * @notice Sets the destination gas overhead for a single domain.
127
+ * @param config The destination domain and gas overhead.
128
+ */
129
+ function _setDestinationGasOverhead(DomainConfig calldata config) internal {
130
+ destinationGasOverhead[config.domain] = config.gasOverhead;
131
+ emit DestinationGasOverheadSet(config.domain, config.gasOverhead);
132
+ }
133
+ }
@@ -0,0 +1,54 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ pragma solidity ^0.8.13;
3
+
4
+ import {Address} from "@openzeppelin/contracts/utils/Address.sol";
5
+
6
+ library CallLib {
7
+ struct Call {
8
+ address to;
9
+ bytes data;
10
+ }
11
+
12
+ function _multicall(address to, bytes[] memory calls) internal {
13
+ uint256 i = 0;
14
+ uint256 len = calls.length;
15
+ while (i < len) {
16
+ Address.functionCall(to, calls[i]);
17
+ unchecked {
18
+ ++i;
19
+ }
20
+ }
21
+ }
22
+
23
+ function _multicall(Call[] memory calls) internal {
24
+ uint256 i = 0;
25
+ uint256 len = calls.length;
26
+ while (i < len) {
27
+ Address.functionCall(calls[i].to, calls[i].data);
28
+ unchecked {
29
+ ++i;
30
+ }
31
+ }
32
+ }
33
+
34
+ function _multicallAndResolve(Call[] memory calls, bytes[] memory callbacks)
35
+ internal
36
+ returns (bytes[] memory resolveCalls)
37
+ {
38
+ // reuse memory
39
+ resolveCalls = callbacks;
40
+
41
+ uint256 i = 0;
42
+ uint256 len = calls.length;
43
+ while (i < len) {
44
+ bytes memory returnData = Address.functionCall(
45
+ calls[i].to,
46
+ calls[i].data
47
+ );
48
+ resolveCalls[i] = bytes.concat(callbacks[i], returnData);
49
+ unchecked {
50
+ ++i;
51
+ }
52
+ }
53
+ }
54
+ }
@@ -0,0 +1,35 @@
1
+ // SPDX-License-Identifier: MIT OR Apache-2.0
2
+ pragma solidity >=0.8.0;
3
+ // ============ Internal Imports ============
4
+ import {TypeCasts} from "./TypeCasts.sol";
5
+ // ============ External Imports ============
6
+ import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
7
+
8
+ library ValidatorAnnouncements {
9
+ using TypeCasts for address;
10
+
11
+ /**
12
+ * @notice Returns the digest validators are expected to sign when signing announcements.
13
+ * @param _mailbox Address of the mailbox being validated
14
+ * @param _localDomain Domain of chain on which the contract is deployed
15
+ * @param _storageLocation Storage location string.
16
+ * @return The digest of the announcement.
17
+ */
18
+ function getAnnouncementDigest(
19
+ address _mailbox,
20
+ uint32 _localDomain,
21
+ string memory _storageLocation
22
+ ) internal pure returns (bytes32) {
23
+ bytes32 _domainHash = keccak256(
24
+ abi.encodePacked(
25
+ _localDomain,
26
+ _mailbox.addressToBytes32(),
27
+ "HYPERLANE"
28
+ )
29
+ );
30
+ return
31
+ ECDSA.toEthSignedMessageHash(
32
+ keccak256(abi.encodePacked(_domainHash, _storageLocation))
33
+ );
34
+ }
35
+ }
@@ -2,10 +2,11 @@
2
2
  pragma solidity ^0.8.13;
3
3
 
4
4
  // ============ Internal Imports ============
5
- import {OwnableMulticall, Call} from "../OwnableMulticall.sol";
5
+ import {OwnableMulticall} from "../OwnableMulticall.sol";
6
6
  import {Router} from "../Router.sol";
7
7
  import {IInterchainAccountRouter} from "../../interfaces/IInterchainAccountRouter.sol";
8
8
  import {MinimalProxy} from "../libs/MinimalProxy.sol";
9
+ import {CallLib} from "../libs/Call.sol";
9
10
 
10
11
  // ============ External Imports ============
11
12
  import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";
@@ -68,7 +69,7 @@ contract InterchainAccountRouter is Router, IInterchainAccountRouter {
68
69
  * @param _destinationDomain The domain of the chain where the message will be sent to.
69
70
  * @param calls The sequence of calls to be relayed.
70
71
  */
71
- function dispatch(uint32 _destinationDomain, Call[] calldata calls)
72
+ function dispatch(uint32 _destinationDomain, CallLib.Call[] calldata calls)
72
73
  external
73
74
  returns (bytes32)
74
75
  {
@@ -87,8 +88,8 @@ contract InterchainAccountRouter is Router, IInterchainAccountRouter {
87
88
  address target,
88
89
  bytes calldata data
89
90
  ) external returns (bytes32) {
90
- Call[] memory calls = new Call[](1);
91
- calls[0] = Call({to: target, data: data});
91
+ CallLib.Call[] memory calls = new CallLib.Call[](1);
92
+ calls[0] = CallLib.Call({to: target, data: data});
92
93
  return _dispatch(_destinationDomain, abi.encode(msg.sender, calls));
93
94
  }
94
95
 
@@ -164,9 +165,9 @@ contract InterchainAccountRouter is Router, IInterchainAccountRouter {
164
165
  bytes32, // router sender
165
166
  bytes calldata _message
166
167
  ) internal override {
167
- (address sender, Call[] memory calls) = abi.decode(
168
+ (address sender, CallLib.Call[] memory calls) = abi.decode(
168
169
  _message,
169
- (address, Call[])
170
+ (address, CallLib.Call[])
170
171
  );
171
172
  getDeployedInterchainAccount(_origin, sender).proxyCalls(calls);
172
173
  }
@@ -2,7 +2,7 @@
2
2
  pragma solidity ^0.8.13;
3
3
 
4
4
  // ============ Internal Imports ============
5
- import {_call, _proxyCallBatch, Call} from "../OwnableMulticall.sol";
5
+ import {CallLib} from "../libs/Call.sol";
6
6
  import {Router} from "../Router.sol";
7
7
  import {IInterchainQueryRouter} from "../../interfaces/IInterchainQueryRouter.sol";
8
8
 
@@ -16,6 +16,9 @@ import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Ini
16
16
  * @dev Currently does not support Sovereign Consensus (user specified Interchain Security Modules).
17
17
  */
18
18
  contract InterchainQueryRouter is Router, IInterchainQueryRouter {
19
+ using CallLib for address;
20
+ using CallLib for CallLib.Call[];
21
+
19
22
  enum Action {
20
23
  DISPATCH,
21
24
  RESOLVE
@@ -81,8 +84,8 @@ contract InterchainQueryRouter is Router, IInterchainQueryRouter {
81
84
  bytes calldata callback
82
85
  ) external returns (bytes32 messageId) {
83
86
  // TODO: fix this ugly arrayification
84
- Call[] memory calls = new Call[](1);
85
- calls[0] = Call({to: target, data: queryData});
87
+ CallLib.Call[] memory calls = new CallLib.Call[](1);
88
+ calls[0] = CallLib.Call({to: target, data: queryData});
86
89
  bytes[] memory callbacks = new bytes[](1);
87
90
  callbacks[0] = callback;
88
91
  messageId = query(_destinationDomain, calls, callbacks);
@@ -95,11 +98,11 @@ contract InterchainQueryRouter is Router, IInterchainQueryRouter {
95
98
  */
96
99
  function query(
97
100
  uint32 _destinationDomain,
98
- Call calldata call,
101
+ CallLib.Call calldata call,
99
102
  bytes calldata callback
100
103
  ) external returns (bytes32 messageId) {
101
104
  // TODO: fix this ugly arrayification
102
- Call[] memory calls = new Call[](1);
105
+ CallLib.Call[] memory calls = new CallLib.Call[](1);
103
106
  calls[0] = call;
104
107
  bytes[] memory callbacks = new bytes[](1);
105
108
  callbacks[0] = callback;
@@ -113,7 +116,7 @@ contract InterchainQueryRouter is Router, IInterchainQueryRouter {
113
116
  */
114
117
  function query(
115
118
  uint32 _destinationDomain,
116
- Call[] memory calls,
119
+ CallLib.Call[] memory calls,
117
120
  bytes[] memory callbacks
118
121
  ) public returns (bytes32 messageId) {
119
122
  require(
@@ -142,21 +145,21 @@ contract InterchainQueryRouter is Router, IInterchainQueryRouter {
142
145
  (
143
146
  ,
144
147
  address sender,
145
- Call[] memory calls,
148
+ CallLib.Call[] memory calls,
146
149
  bytes[] memory callbacks
147
- ) = abi.decode(_message, (Action, address, Call[], bytes[]));
148
- bytes[] memory resolveCallbacks = _call(calls, callbacks);
149
- _dispatch(
150
- _origin,
151
- abi.encode(Action.RESOLVE, sender, resolveCallbacks)
152
- );
150
+ ) = abi.decode(
151
+ _message,
152
+ (Action, address, CallLib.Call[], bytes[])
153
+ );
154
+ callbacks = calls._multicallAndResolve(callbacks);
155
+ _dispatch(_origin, abi.encode(Action.RESOLVE, sender, callbacks));
153
156
  emit QueryReturned(_origin, sender);
154
157
  } else if (action == Action.RESOLVE) {
155
158
  (, address sender, bytes[] memory resolveCallbacks) = abi.decode(
156
159
  _message,
157
160
  (Action, address, bytes[])
158
161
  );
159
- _proxyCallBatch(sender, resolveCallbacks);
162
+ sender._multicall(resolveCallbacks);
160
163
  emit QueryResolved(_origin, sender);
161
164
  }
162
165
  }
@@ -3,7 +3,7 @@ pragma solidity ^0.8.13;
3
3
 
4
4
  import "./MockMailbox.sol";
5
5
  import "../middleware/InterchainQueryRouter.sol";
6
- import "../InterchainGasPaymaster.sol";
6
+ import "../igps/InterchainGasPaymaster.sol";
7
7
  import "../test/TestIsm.sol";
8
8
 
9
9
  import {TypeCasts} from "../libs/TypeCasts.sol";
@@ -8,8 +8,8 @@ contract MockMailbox {
8
8
  using TypeCasts for address;
9
9
  using TypeCasts for bytes32;
10
10
  // Domain of chain on which the contract is deployed
11
- uint32 public immutable domain;
12
- uint32 public immutable version = 0;
11
+ uint32 public immutable localDomain;
12
+ uint32 public immutable VERSION = 0;
13
13
 
14
14
  uint256 public outboundNonce = 0;
15
15
  uint256 public inboundUnprocessedNonce = 0;
@@ -25,7 +25,7 @@ contract MockMailbox {
25
25
  }
26
26
 
27
27
  constructor(uint32 _domain) {
28
- domain = _domain;
28
+ localDomain = _domain;
29
29
  }
30
30
 
31
31
  function addRemoteMailbox(uint32 _domain, MockMailbox _mailbox) external {
@@ -43,7 +43,7 @@ contract MockMailbox {
43
43
  "Missing remote mailbox"
44
44
  );
45
45
  _destinationMailbox.addInboundMessage(
46
- domain,
46
+ localDomain,
47
47
  msg.sender,
48
48
  _recipientAddress.bytes32ToAddress(),
49
49
  _messageBody
@@ -0,0 +1,12 @@
1
+ import "./TestRecipient.sol";
2
+
3
+ contract LightTestRecipient is TestRecipient {
4
+ // solhint-disable-next-line no-empty-blocks
5
+ function handle(
6
+ uint32 _origin,
7
+ bytes32 _sender,
8
+ bytes calldata _data
9
+ ) external override {
10
+ // do nothing
11
+ }
12
+ }
@@ -2,7 +2,6 @@
2
2
  pragma solidity ^0.8.13;
3
3
 
4
4
  import {InterchainQueryRouter} from "../middleware/InterchainQueryRouter.sol";
5
- import {Call} from "../OwnableMulticall.sol";
6
5
  import {TypeCasts} from "../libs/TypeCasts.sol";
7
6
 
8
7
  contract TestQuery {
@@ -18,15 +17,13 @@ contract TestQuery {
18
17
  * @dev Fetches owner of InterchainQueryRouter on provided domain and passes along with provided secret to `this.receiveRouterOwner`
19
18
  */
20
19
  function queryRouterOwner(uint32 domain, uint256 secret) external {
21
- Call memory call = Call({
22
- to: TypeCasts.bytes32ToAddress(router.routers(domain)),
23
- data: abi.encodeWithSignature("owner()")
24
- });
20
+ address target = TypeCasts.bytes32ToAddress(router.routers(domain));
21
+ bytes memory data = abi.encodeWithSignature("owner()");
25
22
  bytes memory callback = bytes.concat(
26
23
  this.receiveRouterOwer.selector,
27
24
  bytes32(secret)
28
25
  );
29
- router.query(domain, call, callback);
26
+ router.query(domain, target, data, callback);
30
27
  }
31
28
 
32
29
  /**