@hyperlane-xyz/core 1.1.3 → 1.1.4

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 (176) hide show
  1. package/contracts/GasRouter.sol +103 -0
  2. package/contracts/OwnableMulticall.sol +5 -4
  3. package/contracts/PausableReentrancyGuard.sol +2 -2
  4. package/contracts/igps/InterchainGasPaymaster.sol +2 -1
  5. package/contracts/libs/Call.sol +108 -19
  6. package/contracts/middleware/InterchainAccountRouter.sol +47 -34
  7. package/contracts/middleware/InterchainCallMessage.sol +112 -0
  8. package/contracts/middleware/InterchainQueryRouter.sol +36 -80
  9. package/contracts/mock/MockHyperlaneEnvironment.sol +4 -4
  10. package/contracts/test/TestGasRouter.sol +28 -0
  11. package/contracts/test/TestInterchainGasPaymaster.sol +8 -17
  12. package/contracts/test/TestQuery.sol +11 -6
  13. package/contracts/test/TestQuerySender.sol +22 -11
  14. package/dist/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol/IERC20Permit.d.ts +75 -0
  15. package/dist/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol/IERC20Permit.d.ts.map +1 -0
  16. package/dist/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol/IERC20Permit.js +4 -0
  17. package/dist/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol/IERC20Permit.js.map +1 -0
  18. package/dist/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol/index.d.ts +2 -0
  19. package/dist/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol/index.d.ts.map +1 -0
  20. package/dist/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol/index.js +3 -0
  21. package/dist/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol/index.js.map +1 -0
  22. package/dist/@openzeppelin/contracts/token/ERC20/extensions/index.d.ts +3 -0
  23. package/dist/@openzeppelin/contracts/token/ERC20/extensions/index.d.ts.map +1 -0
  24. package/dist/@openzeppelin/contracts/token/ERC20/extensions/index.js +4 -0
  25. package/dist/@openzeppelin/contracts/token/ERC20/extensions/index.js.map +1 -0
  26. package/dist/@openzeppelin/contracts/token/ERC20/index.d.ts +2 -0
  27. package/dist/@openzeppelin/contracts/token/ERC20/index.d.ts.map +1 -1
  28. package/dist/@openzeppelin/contracts/token/ERC20/index.js +1 -0
  29. package/dist/@openzeppelin/contracts/token/ERC20/index.js.map +1 -1
  30. package/dist/contracts/GasRouter.d.ts +336 -0
  31. package/dist/contracts/GasRouter.d.ts.map +1 -0
  32. package/dist/contracts/GasRouter.js +4 -0
  33. package/dist/contracts/GasRouter.js.map +1 -0
  34. package/dist/contracts/InterchainGasPaymaster.d.ts +162 -0
  35. package/dist/contracts/InterchainGasPaymaster.d.ts.map +1 -0
  36. package/dist/contracts/InterchainGasPaymaster.js +4 -0
  37. package/dist/contracts/InterchainGasPaymaster.js.map +1 -0
  38. package/dist/contracts/OwnableMulticall.d.ts +13 -5
  39. package/dist/contracts/OwnableMulticall.d.ts.map +1 -1
  40. package/dist/contracts/igps/GasOverheadIgp.d.ts +194 -0
  41. package/dist/contracts/igps/GasOverheadIgp.d.ts.map +1 -0
  42. package/dist/contracts/igps/GasOverheadIgp.js +4 -0
  43. package/dist/contracts/igps/GasOverheadIgp.js.map +1 -0
  44. package/dist/contracts/index.d.ts +1 -0
  45. package/dist/contracts/index.d.ts.map +1 -1
  46. package/dist/contracts/middleware/InterchainAccountRouter.d.ts +60 -44
  47. package/dist/contracts/middleware/InterchainAccountRouter.d.ts.map +1 -1
  48. package/dist/contracts/middleware/InterchainQueryRouter.d.ts +36 -57
  49. package/dist/contracts/middleware/InterchainQueryRouter.d.ts.map +1 -1
  50. package/dist/contracts/middleware/liquidity-layer/interfaces/circle/ICircleBridge.d.ts +78 -0
  51. package/dist/contracts/middleware/liquidity-layer/interfaces/circle/ICircleBridge.d.ts.map +1 -0
  52. package/dist/contracts/middleware/liquidity-layer/interfaces/circle/ICircleBridge.js +4 -0
  53. package/dist/contracts/middleware/liquidity-layer/interfaces/circle/ICircleBridge.js.map +1 -0
  54. package/dist/contracts/mock/MockCircleBridge.d.ts +86 -0
  55. package/dist/contracts/mock/MockCircleBridge.d.ts.map +1 -0
  56. package/dist/contracts/mock/MockCircleBridge.js +4 -0
  57. package/dist/contracts/mock/MockCircleBridge.js.map +1 -0
  58. package/dist/contracts/mock/MockInterchainAccountRouter.d.ts +422 -0
  59. package/dist/contracts/mock/MockInterchainAccountRouter.d.ts.map +1 -0
  60. package/dist/contracts/mock/MockInterchainAccountRouter.js +4 -0
  61. package/dist/contracts/mock/MockInterchainAccountRouter.js.map +1 -0
  62. package/dist/contracts/test/TestGasRouter.d.ts +441 -0
  63. package/dist/contracts/test/TestGasRouter.d.ts.map +1 -0
  64. package/dist/contracts/test/TestGasRouter.js +4 -0
  65. package/dist/contracts/test/TestGasRouter.js.map +1 -0
  66. package/dist/contracts/test/TestInterchainGasPaymaster.d.ts +122 -12
  67. package/dist/contracts/test/TestInterchainGasPaymaster.d.ts.map +1 -1
  68. package/dist/contracts/test/TestQuery.d.ts +9 -9
  69. package/dist/contracts/test/TestQuery.d.ts.map +1 -1
  70. package/dist/contracts/test/index.d.ts +1 -0
  71. package/dist/contracts/test/index.d.ts.map +1 -1
  72. package/dist/factories/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol/IERC20Permit__factory.d.ts +23 -0
  73. package/dist/factories/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol/IERC20Permit__factory.d.ts.map +1 -0
  74. package/dist/factories/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol/IERC20Permit__factory.js +93 -0
  75. package/dist/factories/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol/IERC20Permit__factory.js.map +1 -0
  76. package/dist/factories/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol/index.d.ts +2 -0
  77. package/dist/factories/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol/index.d.ts.map +1 -0
  78. package/dist/factories/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol/index.js +9 -0
  79. package/dist/factories/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol/index.js.map +1 -0
  80. package/dist/factories/@openzeppelin/contracts/token/ERC20/extensions/index.d.ts +2 -0
  81. package/dist/factories/@openzeppelin/contracts/token/ERC20/extensions/index.d.ts.map +1 -0
  82. package/dist/factories/@openzeppelin/contracts/token/ERC20/extensions/index.js +31 -0
  83. package/dist/factories/@openzeppelin/contracts/token/ERC20/extensions/index.js.map +1 -0
  84. package/dist/factories/@openzeppelin/contracts/token/ERC20/index.d.ts +1 -0
  85. package/dist/factories/@openzeppelin/contracts/token/ERC20/index.d.ts.map +1 -1
  86. package/dist/factories/@openzeppelin/contracts/token/ERC20/index.js +25 -1
  87. package/dist/factories/@openzeppelin/contracts/token/ERC20/index.js.map +1 -1
  88. package/dist/factories/contracts/GasRouter__factory.d.ts +52 -0
  89. package/dist/factories/contracts/GasRouter__factory.d.ts.map +1 -0
  90. package/dist/factories/contracts/GasRouter__factory.js +392 -0
  91. package/dist/factories/contracts/GasRouter__factory.js.map +1 -0
  92. package/dist/factories/contracts/InterchainGasPaymaster__factory.d.ts +62 -0
  93. package/dist/factories/contracts/InterchainGasPaymaster__factory.d.ts.map +1 -0
  94. package/dist/factories/contracts/InterchainGasPaymaster__factory.js +178 -0
  95. package/dist/factories/contracts/InterchainGasPaymaster__factory.js.map +1 -0
  96. package/dist/factories/contracts/Mailbox__factory.d.ts +1 -1
  97. package/dist/factories/contracts/Mailbox__factory.js +1 -1
  98. package/dist/factories/contracts/OwnableMulticall__factory.d.ts +20 -3
  99. package/dist/factories/contracts/OwnableMulticall__factory.d.ts.map +1 -1
  100. package/dist/factories/contracts/OwnableMulticall__factory.js +23 -7
  101. package/dist/factories/contracts/OwnableMulticall__factory.js.map +1 -1
  102. package/dist/factories/contracts/igps/GasOverheadIgp__factory.d.ts +75 -0
  103. package/dist/factories/contracts/igps/GasOverheadIgp__factory.d.ts.map +1 -0
  104. package/dist/factories/contracts/igps/GasOverheadIgp__factory.js +263 -0
  105. package/dist/factories/contracts/igps/GasOverheadIgp__factory.js.map +1 -0
  106. package/dist/factories/contracts/igps/InterchainGasPaymaster__factory.d.ts +1 -1
  107. package/dist/factories/contracts/igps/InterchainGasPaymaster__factory.js +2 -2
  108. package/dist/factories/contracts/index.d.ts +1 -0
  109. package/dist/factories/contracts/index.d.ts.map +1 -1
  110. package/dist/factories/contracts/index.js +3 -1
  111. package/dist/factories/contracts/index.js.map +1 -1
  112. package/dist/factories/contracts/middleware/InterchainAccountRouter__factory.d.ts +13 -3
  113. package/dist/factories/contracts/middleware/InterchainAccountRouter__factory.d.ts.map +1 -1
  114. package/dist/factories/contracts/middleware/InterchainAccountRouter__factory.js +70 -39
  115. package/dist/factories/contracts/middleware/InterchainAccountRouter__factory.js.map +1 -1
  116. package/dist/factories/contracts/middleware/InterchainQueryRouter__factory.d.ts +13 -3
  117. package/dist/factories/contracts/middleware/InterchainQueryRouter__factory.d.ts.map +1 -1
  118. package/dist/factories/contracts/middleware/InterchainQueryRouter__factory.js +24 -92
  119. package/dist/factories/contracts/middleware/InterchainQueryRouter__factory.js.map +1 -1
  120. package/dist/factories/contracts/middleware/liquidity-layer/interfaces/circle/ICircleBridge__factory.d.ts +36 -0
  121. package/dist/factories/contracts/middleware/liquidity-layer/interfaces/circle/ICircleBridge__factory.d.ts.map +1 -0
  122. package/dist/factories/contracts/middleware/liquidity-layer/interfaces/circle/ICircleBridge__factory.js +104 -0
  123. package/dist/factories/contracts/middleware/liquidity-layer/interfaces/circle/ICircleBridge__factory.js.map +1 -0
  124. package/dist/factories/contracts/mock/MockCircleBridge__factory.d.ts +59 -0
  125. package/dist/factories/contracts/mock/MockCircleBridge__factory.d.ts.map +1 -0
  126. package/dist/factories/contracts/mock/MockCircleBridge__factory.js +151 -0
  127. package/dist/factories/contracts/mock/MockCircleBridge__factory.js.map +1 -0
  128. package/dist/factories/contracts/mock/MockHyperlaneEnvironment__factory.d.ts +1 -1
  129. package/dist/factories/contracts/mock/MockHyperlaneEnvironment__factory.d.ts.map +1 -1
  130. package/dist/factories/contracts/mock/MockHyperlaneEnvironment__factory.js +2 -2
  131. package/dist/factories/contracts/mock/MockHyperlaneEnvironment__factory.js.map +1 -1
  132. package/dist/factories/contracts/mock/MockInterchainAccountRouter__factory.d.ts +69 -0
  133. package/dist/factories/contracts/mock/MockInterchainAccountRouter__factory.d.ts.map +1 -0
  134. package/dist/factories/contracts/mock/MockInterchainAccountRouter__factory.js +556 -0
  135. package/dist/factories/contracts/mock/MockInterchainAccountRouter__factory.js.map +1 -0
  136. package/dist/factories/contracts/test/TestGasRouter__factory.d.ts +64 -0
  137. package/dist/factories/contracts/test/TestGasRouter__factory.d.ts.map +1 -0
  138. package/dist/factories/contracts/test/TestGasRouter__factory.js +579 -0
  139. package/dist/factories/contracts/test/TestGasRouter__factory.js.map +1 -0
  140. package/dist/factories/contracts/test/TestInterchainGasPaymaster__factory.d.ts +1 -1
  141. package/dist/factories/contracts/test/TestInterchainGasPaymaster__factory.d.ts.map +1 -1
  142. package/dist/factories/contracts/test/TestInterchainGasPaymaster__factory.js +97 -5
  143. package/dist/factories/contracts/test/TestInterchainGasPaymaster__factory.js.map +1 -1
  144. package/dist/factories/contracts/test/TestMailbox__factory.d.ts +1 -1
  145. package/dist/factories/contracts/test/TestMailbox__factory.js +1 -1
  146. package/dist/factories/contracts/test/TestQuerySender__factory.d.ts +1 -1
  147. package/dist/factories/contracts/test/TestQuerySender__factory.d.ts.map +1 -1
  148. package/dist/factories/contracts/test/TestQuerySender__factory.js +1 -1
  149. package/dist/factories/contracts/test/TestQuerySender__factory.js.map +1 -1
  150. package/dist/factories/contracts/test/TestQuery__factory.d.ts +1 -1
  151. package/dist/factories/contracts/test/TestQuery__factory.d.ts.map +1 -1
  152. package/dist/factories/contracts/test/TestQuery__factory.js +2 -2
  153. package/dist/factories/contracts/test/TestQuery__factory.js.map +1 -1
  154. package/dist/factories/contracts/test/index.d.ts +1 -0
  155. package/dist/factories/contracts/test/index.d.ts.map +1 -1
  156. package/dist/factories/contracts/test/index.js +3 -1
  157. package/dist/factories/contracts/test/index.js.map +1 -1
  158. package/dist/factories/interfaces/IInterchainAccountRouter__factory.d.ts +12 -2
  159. package/dist/factories/interfaces/IInterchainAccountRouter__factory.d.ts.map +1 -1
  160. package/dist/factories/interfaces/IInterchainAccountRouter__factory.js +27 -20
  161. package/dist/factories/interfaces/IInterchainAccountRouter__factory.js.map +1 -1
  162. package/dist/factories/interfaces/IInterchainQueryRouter__factory.d.ts +12 -2
  163. package/dist/factories/interfaces/IInterchainQueryRouter__factory.d.ts.map +1 -1
  164. package/dist/factories/interfaces/IInterchainQueryRouter__factory.js +17 -85
  165. package/dist/factories/interfaces/IInterchainQueryRouter__factory.js.map +1 -1
  166. package/dist/index.d.ts +6 -0
  167. package/dist/index.d.ts.map +1 -1
  168. package/dist/index.js +8 -2
  169. package/dist/index.js.map +1 -1
  170. package/dist/interfaces/IInterchainAccountRouter.d.ts +35 -35
  171. package/dist/interfaces/IInterchainAccountRouter.d.ts.map +1 -1
  172. package/dist/interfaces/IInterchainQueryRouter.d.ts +23 -44
  173. package/dist/interfaces/IInterchainQueryRouter.d.ts.map +1 -1
  174. package/interfaces/IInterchainAccountRouter.sol +5 -6
  175. package/interfaces/IInterchainQueryRouter.sol +1 -15
  176. package/package.json +5 -4
@@ -0,0 +1,103 @@
1
+ // SPDX-License-Identifier: MIT OR Apache-2.0
2
+ pragma solidity >=0.6.11;
3
+
4
+ import {Router} from "./Router.sol";
5
+
6
+ abstract contract GasRouter is Router {
7
+ // ============ Mutable Storage ============
8
+ mapping(uint32 => uint256) public destinationGas;
9
+
10
+ // ============ Events ============
11
+
12
+ /**
13
+ * @notice Emitted when a domain's destination gas is set.
14
+ * @param domain The domain of the router.
15
+ * @param gas The gas amount used by the handle function of the domain's router.
16
+ */
17
+ event DestinationGasSet(uint32 indexed domain, uint256 gas);
18
+
19
+ struct GasRouterConfig {
20
+ uint32 domain;
21
+ uint256 gas;
22
+ }
23
+
24
+ /**
25
+ * @notice Sets the gas amount dispatched for each configured domain.
26
+ * @param gasConfigs The array of GasRouterConfig structs
27
+ */
28
+ function setDestinationGas(GasRouterConfig[] calldata gasConfigs)
29
+ external
30
+ onlyOwner
31
+ {
32
+ for (uint256 i = 0; i < gasConfigs.length; i += 1) {
33
+ _setDestinationGas(gasConfigs[i].domain, gasConfigs[i].gas);
34
+ }
35
+ }
36
+
37
+ /**
38
+ * @notice Returns the gas payment required to dispatch a message to the given domain's router.
39
+ * @param _destinationDomain The domain of the router.
40
+ * @return _gasPayment Payment computed by the registered InterchainGasPaymaster.
41
+ */
42
+ function quoteGasPayment(uint32 _destinationDomain)
43
+ external
44
+ view
45
+ returns (uint256 _gasPayment)
46
+ {
47
+ return
48
+ interchainGasPaymaster.quoteGasPayment(
49
+ _destinationDomain,
50
+ destinationGas[_destinationDomain]
51
+ );
52
+ }
53
+
54
+ function _setDestinationGas(uint32 domain, uint256 gas) internal {
55
+ destinationGas[domain] = gas;
56
+ emit DestinationGasSet(domain, gas);
57
+ }
58
+
59
+ /**
60
+ * @dev Uses the destinationGas mapping to populate the gas amount for the message.
61
+ * @notice Dispatches a message to an enrolled router via the local router's Mailbox
62
+ * and pays for it to be relayed to the destination.
63
+ * @dev Reverts if there is no enrolled router for _destinationDomain.
64
+ * @param _destinationDomain The domain of the chain to which to send the message.
65
+ * @param _messageBody Raw bytes content of message.
66
+ * @param _gasPayment The amount of native tokens to pay for the message to be relayed.
67
+ * @param _gasPaymentRefundAddress The address to refund any gas overpayment to.
68
+ */
69
+ function _dispatchWithGas(
70
+ uint32 _destinationDomain,
71
+ bytes memory _messageBody,
72
+ uint256 _gasPayment,
73
+ address _gasPaymentRefundAddress
74
+ ) internal returns (bytes32 _messageId) {
75
+ return
76
+ _dispatchWithGas(
77
+ _destinationDomain,
78
+ _messageBody,
79
+ destinationGas[_destinationDomain],
80
+ _gasPayment,
81
+ _gasPaymentRefundAddress
82
+ );
83
+ }
84
+
85
+ /**
86
+ * @dev Passes `msg.value` as gas payment and `msg.sender` as gas payment refund address.
87
+ * @dev Uses the destinationGas mapping to populate the gas amount for the message.
88
+ * @param _destinationDomain The domain of the chain to send the message.
89
+ * @param _messageBody Raw bytes content of message.
90
+ */
91
+ function _dispatchWithGas(
92
+ uint32 _destinationDomain,
93
+ bytes memory _messageBody
94
+ ) internal returns (bytes32 _messageId) {
95
+ return
96
+ _dispatchWithGas(
97
+ _destinationDomain,
98
+ _messageBody,
99
+ msg.value,
100
+ msg.sender
101
+ );
102
+ }
103
+ }
@@ -9,11 +9,9 @@ import {CallLib} from "./libs/Call.sol";
9
9
 
10
10
  /*
11
11
  * @title OwnableMulticall
12
- * @dev Allows only only address to execute calls to other contracts
12
+ * @dev Permits owner address to execute state mutating calls with value to other contracts
13
13
  */
14
14
  contract OwnableMulticall is OwnableUpgradeable {
15
- using CallLib for CallLib.Call[];
16
-
17
15
  constructor() {
18
16
  _transferOwnership(msg.sender);
19
17
  }
@@ -23,6 +21,9 @@ contract OwnableMulticall is OwnableUpgradeable {
23
21
  }
24
22
 
25
23
  function proxyCalls(CallLib.Call[] calldata calls) external onlyOwner {
26
- calls._multicall();
24
+ return CallLib.multicall(calls);
27
25
  }
26
+
27
+ // solhint-disable-next-line no-empty-blocks
28
+ receive() external payable {}
28
29
  }
@@ -5,9 +5,9 @@ import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
5
5
 
6
6
  // adapted from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
7
7
  abstract contract PausableReentrancyGuardUpgradeable is Initializable {
8
+ uint256 private constant _ENTERED = 0;
8
9
  uint256 private constant _NOT_ENTERED = 1;
9
- uint256 private constant _ENTERED = 2;
10
- uint256 private constant _PAUSED = 3;
10
+ uint256 private constant _PAUSED = 2;
11
11
 
12
12
  uint256 private _status;
13
13
 
@@ -79,7 +79,8 @@ contract InterchainGasPaymaster is IInterchainGasPaymaster, OwnableUpgradeable {
79
79
  */
80
80
  function quoteGasPayment(uint32 _destinationDomain, uint256 _gasAmount)
81
81
  public
82
- pure
82
+ view
83
+ virtual
83
84
  override
84
85
  returns (uint256)
85
86
  {
@@ -3,52 +3,141 @@ pragma solidity ^0.8.13;
3
3
 
4
4
  import {Address} from "@openzeppelin/contracts/utils/Address.sol";
5
5
 
6
+ import {TypeCasts} from "./TypeCasts.sol";
7
+
6
8
  library CallLib {
7
- struct Call {
8
- address to;
9
+ struct StaticCall {
10
+ // supporting non EVM targets
11
+ bytes32 to;
9
12
  bytes data;
10
13
  }
11
14
 
12
- function _multicall(address to, bytes[] memory calls) internal {
15
+ struct Call {
16
+ uint256 value;
17
+ StaticCall _call;
18
+ }
19
+
20
+ struct StaticCallWithCallback {
21
+ StaticCall _call;
22
+ bytes callback;
23
+ }
24
+
25
+ function target(StaticCall memory _call) internal pure returns (address) {
26
+ return TypeCasts.bytes32ToAddress(_call.to);
27
+ }
28
+
29
+ function call(Call memory _call)
30
+ internal
31
+ returns (bytes memory returnData)
32
+ {
33
+ return
34
+ Address.functionCallWithValue(
35
+ target(_call._call),
36
+ _call._call.data,
37
+ _call.value
38
+ );
39
+ }
40
+
41
+ function staticcall(StaticCall memory _call)
42
+ private
43
+ view
44
+ returns (bytes memory)
45
+ {
46
+ return Address.functionStaticCall(target(_call), _call.data);
47
+ }
48
+
49
+ function staticcall(StaticCallWithCallback memory _call)
50
+ internal
51
+ view
52
+ returns (bytes memory callback)
53
+ {
54
+ return bytes.concat(_call.callback, staticcall(_call._call));
55
+ }
56
+
57
+ function multicall(Call[] memory calls) internal {
13
58
  uint256 i = 0;
14
59
  uint256 len = calls.length;
15
60
  while (i < len) {
16
- Address.functionCall(to, calls[i]);
61
+ call(calls[i]);
17
62
  unchecked {
18
63
  ++i;
19
64
  }
20
65
  }
21
66
  }
22
67
 
23
- function _multicall(Call[] memory calls) internal {
68
+ function multistaticcall(StaticCallWithCallback[] memory _calls)
69
+ internal
70
+ view
71
+ returns (bytes[] memory)
72
+ {
24
73
  uint256 i = 0;
25
- uint256 len = calls.length;
74
+ uint256 len = _calls.length;
75
+ bytes[] memory callbacks = new bytes[](len);
26
76
  while (i < len) {
27
- Address.functionCall(calls[i].to, calls[i].data);
77
+ callbacks[i] = staticcall(_calls[i]);
28
78
  unchecked {
29
79
  ++i;
30
80
  }
31
81
  }
82
+ return callbacks;
32
83
  }
33
84
 
34
- function _multicallAndResolve(Call[] memory calls, bytes[] memory callbacks)
35
- internal
36
- returns (bytes[] memory resolveCalls)
37
- {
38
- // reuse memory
39
- resolveCalls = callbacks;
40
-
85
+ function multicallto(address to, bytes[] memory calls) internal {
41
86
  uint256 i = 0;
42
87
  uint256 len = calls.length;
43
88
  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);
89
+ Address.functionCall(to, calls[i]);
49
90
  unchecked {
50
91
  ++i;
51
92
  }
52
93
  }
53
94
  }
95
+
96
+ function build(bytes32 to, bytes memory data)
97
+ internal
98
+ pure
99
+ returns (StaticCall memory)
100
+ {
101
+ return StaticCall(to, data);
102
+ }
103
+
104
+ function build(address to, bytes memory data)
105
+ internal
106
+ pure
107
+ returns (StaticCall memory)
108
+ {
109
+ return build(TypeCasts.addressToBytes32(to), data);
110
+ }
111
+
112
+ function build(
113
+ bytes32 to,
114
+ uint256 value,
115
+ bytes memory data
116
+ ) internal pure returns (Call memory) {
117
+ return Call(value, build(to, data));
118
+ }
119
+
120
+ function build(
121
+ address to,
122
+ uint256 value,
123
+ bytes memory data
124
+ ) internal pure returns (Call memory) {
125
+ return Call(value, build(to, data));
126
+ }
127
+
128
+ function build(
129
+ bytes32 to,
130
+ bytes memory data,
131
+ bytes memory callback
132
+ ) internal pure returns (StaticCallWithCallback memory) {
133
+ return StaticCallWithCallback(build(to, data), callback);
134
+ }
135
+
136
+ function build(
137
+ address to,
138
+ bytes memory data,
139
+ bytes memory callback
140
+ ) internal pure returns (StaticCallWithCallback memory) {
141
+ return StaticCallWithCallback(build(to, data), callback);
142
+ }
54
143
  }
@@ -5,8 +5,10 @@ pragma solidity ^0.8.13;
5
5
  import {OwnableMulticall} from "../OwnableMulticall.sol";
6
6
  import {Router} from "../Router.sol";
7
7
  import {IInterchainAccountRouter} from "../../interfaces/IInterchainAccountRouter.sol";
8
+ import {InterchainCallMessage} from "./InterchainCallMessage.sol";
8
9
  import {MinimalProxy} from "../libs/MinimalProxy.sol";
9
10
  import {CallLib} from "../libs/Call.sol";
11
+ import {TypeCasts} from "../libs/TypeCasts.sol";
10
12
 
11
13
  // ============ External Imports ============
12
14
  import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";
@@ -18,8 +20,11 @@ import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Ini
18
20
  * @dev Currently does not support Sovereign Consensus (user specified Interchain Security Modules).
19
21
  */
20
22
  contract InterchainAccountRouter is Router, IInterchainAccountRouter {
21
- address immutable implementation;
22
- bytes32 immutable bytecodeHash;
23
+ using TypeCasts for address;
24
+ using TypeCasts for bytes32;
25
+
26
+ address internal immutable implementation;
27
+ bytes32 internal immutable bytecodeHash;
23
28
 
24
29
  /**
25
30
  * @notice Emitted when an interchain account is created (first time message is sent from a given `origin`/`sender` pair)
@@ -29,7 +34,7 @@ contract InterchainAccountRouter is Router, IInterchainAccountRouter {
29
34
  */
30
35
  event InterchainAccountCreated(
31
36
  uint32 indexed origin,
32
- address sender,
37
+ bytes32 sender,
33
38
  address account
34
39
  );
35
40
 
@@ -68,29 +73,20 @@ contract InterchainAccountRouter is Router, IInterchainAccountRouter {
68
73
  * @notice Dispatches a sequence of calls to be relayed by the sender's interchain account on the destination domain.
69
74
  * @param _destinationDomain The domain of the chain where the message will be sent to.
70
75
  * @param calls The sequence of calls to be relayed.
76
+ * @dev Recommend using CallLib.build to format the interchain calls.
71
77
  */
72
78
  function dispatch(uint32 _destinationDomain, CallLib.Call[] calldata calls)
73
79
  external
74
80
  returns (bytes32)
75
81
  {
76
- return _dispatch(_destinationDomain, abi.encode(msg.sender, calls));
77
- }
78
-
79
- /**
80
- * @notice Dispatches a single call to be relayed by the sender's interchain account on the destination domain.
81
- * @param _destinationDomain The domain of the chain where the message will be sent to.
82
- * @param target The address of the contract to be called.
83
- * @param data The ABI-encoded data to be called on target contract.
84
- * @return The message ID of the dispatched message.
85
- */
86
- function dispatch(
87
- uint32 _destinationDomain,
88
- address target,
89
- bytes calldata data
90
- ) external returns (bytes32) {
91
- CallLib.Call[] memory calls = new CallLib.Call[](1);
92
- calls[0] = CallLib.Call({to: target, data: data});
93
- return _dispatch(_destinationDomain, abi.encode(msg.sender, calls));
82
+ return
83
+ _dispatch(
84
+ _destinationDomain,
85
+ InterchainCallMessage.format(
86
+ calls,
87
+ msg.sender.addressToBytes32()
88
+ )
89
+ );
94
90
  }
95
91
 
96
92
  /**
@@ -99,42 +95,59 @@ contract InterchainAccountRouter is Router, IInterchainAccountRouter {
99
95
  * @param _sender The parent account address on the origin domain.
100
96
  * @return The address of the interchain account.
101
97
  */
102
- function getInterchainAccount(uint32 _origin, address _sender)
98
+ function getInterchainAccount(uint32 _origin, bytes32 _sender)
103
99
  public
104
100
  view
105
- returns (address)
101
+ returns (address payable)
106
102
  {
107
103
  return _getInterchainAccount(_salt(_origin, _sender));
108
104
  }
109
105
 
106
+ function getInterchainAccount(uint32 _origin, address _sender)
107
+ external
108
+ view
109
+ returns (address payable)
110
+ {
111
+ return getInterchainAccount(_origin, _sender.addressToBytes32());
112
+ }
113
+
110
114
  /**
111
115
  * @notice Returns and deploys (if not already) the interchain account for a given `origin`/`sender` pair.
112
116
  * @param _origin The origin domain of the interchain account.
113
117
  * @param _sender The parent account address on the origin domain.
114
118
  * @return The address of the interchain account.
115
119
  */
116
- function getDeployedInterchainAccount(uint32 _origin, address _sender)
120
+ function getDeployedInterchainAccount(uint32 _origin, bytes32 _sender)
117
121
  public
118
122
  returns (OwnableMulticall)
119
123
  {
120
124
  bytes32 salt = _salt(_origin, _sender);
121
- address interchainAccount = _getInterchainAccount(salt);
125
+ address payable interchainAccount = _getInterchainAccount(salt);
122
126
  if (!Address.isContract(interchainAccount)) {
123
127
  bytes memory bytecode = MinimalProxy.bytecode(implementation);
124
- interchainAccount = Create2.deploy(0, salt, bytecode);
125
- OwnableMulticall(interchainAccount).initialize();
128
+ interchainAccount = payable(Create2.deploy(0, salt, bytecode));
126
129
  emit InterchainAccountCreated(_origin, _sender, interchainAccount);
130
+ // transfers ownership to this contract
131
+ OwnableMulticall(interchainAccount).initialize();
127
132
  }
128
133
  return OwnableMulticall(interchainAccount);
129
134
  }
130
135
 
136
+ function getDeployedInterchainAccount(uint32 _origin, address _sender)
137
+ public
138
+ returns (OwnableMulticall)
139
+ {
140
+ return
141
+ getDeployedInterchainAccount(_origin, _sender.addressToBytes32());
142
+ }
143
+
131
144
  /**
132
145
  * @notice Returns the salt used to deploy the interchain account for a given `origin`/`sender` pair.
133
146
  * @param _origin The origin domain of the interchain account.
134
147
  * @param _sender The parent account address on the origin domain.
135
148
  * @return The CREATE2 salt used for deploying the interchain account.
136
149
  */
137
- function _salt(uint32 _origin, address _sender)
150
+ function _salt(uint32 _origin, bytes32 _sender)
138
151
  internal
139
152
  pure
140
153
  returns (bytes32)
@@ -150,9 +163,9 @@ contract InterchainAccountRouter is Router, IInterchainAccountRouter {
150
163
  function _getInterchainAccount(bytes32 salt)
151
164
  internal
152
165
  view
153
- returns (address)
166
+ returns (address payable)
154
167
  {
155
- return Create2.computeAddress(salt, bytecodeHash);
168
+ return payable(Create2.computeAddress(salt, bytecodeHash));
156
169
  }
157
170
 
158
171
  /**
@@ -165,10 +178,10 @@ contract InterchainAccountRouter is Router, IInterchainAccountRouter {
165
178
  bytes32, // router sender
166
179
  bytes calldata _message
167
180
  ) internal override {
168
- (address sender, CallLib.Call[] memory calls) = abi.decode(
169
- _message,
170
- (address, CallLib.Call[])
181
+ OwnableMulticall interchainAccount = getDeployedInterchainAccount(
182
+ _origin,
183
+ InterchainCallMessage.sender(_message)
171
184
  );
172
- getDeployedInterchainAccount(_origin, sender).proxyCalls(calls);
185
+ interchainAccount.proxyCalls(InterchainCallMessage.calls(_message));
173
186
  }
174
187
  }
@@ -0,0 +1,112 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ pragma solidity ^0.8.13;
3
+
4
+ import {CallLib} from "../libs/Call.sol";
5
+
6
+ /**
7
+ * Format of metadata:
8
+ * [ 0: 32] Sender address
9
+ * [ 32:64] Call type (left padded with zeroes)
10
+ * [ 64:???] Encoded call array
11
+ */
12
+ library InterchainCallMessage {
13
+ uint256 private constant SENDER_OFFSET = 0;
14
+ uint256 private constant TYPE_OFFSET = 32;
15
+ uint256 private constant CALLS_OFFSET = 64;
16
+
17
+ enum CallType {
18
+ CALL,
19
+ STATIC_CALL,
20
+ STATIC_CALL_WITH_CALLBACK,
21
+ RAW_CALLDATA
22
+ }
23
+
24
+ function sender(bytes calldata _message) internal pure returns (bytes32) {
25
+ return bytes32(_message[SENDER_OFFSET:TYPE_OFFSET]);
26
+ }
27
+
28
+ function calltype(bytes calldata _message)
29
+ internal
30
+ pure
31
+ returns (CallType)
32
+ {
33
+ // left padded with zeroes
34
+ return CallType(uint8(bytes1(_message[CALLS_OFFSET - 1])));
35
+ }
36
+
37
+ function format(CallLib.Call[] calldata _calls, bytes32 _sender)
38
+ internal
39
+ pure
40
+ returns (bytes memory)
41
+ {
42
+ return abi.encode(_sender, CallType.CALL, _calls);
43
+ }
44
+
45
+ function calls(bytes calldata _message)
46
+ internal
47
+ pure
48
+ returns (CallLib.Call[] memory _calls)
49
+ {
50
+ assert(calltype(_message) == CallType.CALL);
51
+ (, , _calls) = abi.decode(
52
+ _message,
53
+ (bytes32, CallType, CallLib.Call[])
54
+ );
55
+ }
56
+
57
+ function format(CallLib.StaticCall[] calldata _calls, bytes32 _sender)
58
+ internal
59
+ pure
60
+ returns (bytes memory)
61
+ {
62
+ return abi.encode(_sender, CallType.STATIC_CALL, _calls);
63
+ }
64
+
65
+ function staticCalls(bytes calldata _message)
66
+ internal
67
+ pure
68
+ returns (CallLib.StaticCall[] memory _calls)
69
+ {
70
+ assert(calltype(_message) == CallType.STATIC_CALL);
71
+ (, , _calls) = abi.decode(
72
+ _message,
73
+ (bytes32, CallType, CallLib.StaticCall[])
74
+ );
75
+ }
76
+
77
+ function format(
78
+ CallLib.StaticCallWithCallback[] calldata _calls,
79
+ bytes32 _sender
80
+ ) internal pure returns (bytes memory) {
81
+ return abi.encode(_sender, CallType.STATIC_CALL_WITH_CALLBACK, _calls);
82
+ }
83
+
84
+ function callsWithCallbacks(bytes calldata _message)
85
+ internal
86
+ pure
87
+ returns (CallLib.StaticCallWithCallback[] memory _calls)
88
+ {
89
+ assert(calltype(_message) == CallType.STATIC_CALL_WITH_CALLBACK);
90
+ (, , _calls) = abi.decode(
91
+ _message,
92
+ (bytes32, CallType, CallLib.StaticCallWithCallback[])
93
+ );
94
+ }
95
+
96
+ function format(bytes[] memory _calls, bytes32 _sender)
97
+ internal
98
+ pure
99
+ returns (bytes memory)
100
+ {
101
+ return abi.encode(_sender, CallType.RAW_CALLDATA, _calls);
102
+ }
103
+
104
+ function rawCalls(bytes calldata _message)
105
+ internal
106
+ pure
107
+ returns (bytes[] memory _calls)
108
+ {
109
+ assert(calltype(_message) == CallType.RAW_CALLDATA);
110
+ (, , _calls) = abi.decode(_message, (bytes32, CallType, bytes[]));
111
+ }
112
+ }