@hyperlane-xyz/sdk 42.0.0 → 43.0.0

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 (206) hide show
  1. package/dist/consts/multisigIsm.d.ts.map +1 -1
  2. package/dist/consts/multisigIsm.js +12 -0
  3. package/dist/consts/multisigIsm.js.map +1 -1
  4. package/dist/core/types.d.ts +47 -1635
  5. package/dist/core/types.d.ts.map +1 -1
  6. package/dist/core/types.js +2 -2
  7. package/dist/core/types.js.map +1 -1
  8. package/dist/deploy/HyperlaneDeployer.js +1 -1
  9. package/dist/deploy/proxy.d.ts +8 -40
  10. package/dist/deploy/proxy.d.ts.map +1 -1
  11. package/dist/deploy/proxy.js +4 -4
  12. package/dist/deploy/proxy.js.map +1 -1
  13. package/dist/deploy/types.d.ts +1 -19
  14. package/dist/deploy/types.d.ts.map +1 -1
  15. package/dist/fee/EvmTokenFeeDeployer.d.ts.map +1 -1
  16. package/dist/fee/EvmTokenFeeDeployer.hardhat-test.js +68 -0
  17. package/dist/fee/EvmTokenFeeDeployer.hardhat-test.js.map +1 -1
  18. package/dist/fee/EvmTokenFeeDeployer.js +18 -10
  19. package/dist/fee/EvmTokenFeeDeployer.js.map +1 -1
  20. package/dist/fee/EvmTokenFeeModule.d.ts.map +1 -1
  21. package/dist/fee/EvmTokenFeeModule.hardhat-test.js +18 -8
  22. package/dist/fee/EvmTokenFeeModule.hardhat-test.js.map +1 -1
  23. package/dist/fee/EvmTokenFeeModule.js +8 -1
  24. package/dist/fee/EvmTokenFeeModule.js.map +1 -1
  25. package/dist/fee/EvmTokenFeeReader.d.ts +2 -2
  26. package/dist/fee/EvmTokenFeeReader.d.ts.map +1 -1
  27. package/dist/fee/EvmTokenFeeReader.js.map +1 -1
  28. package/dist/fee/feeConfigMapping.d.ts.map +1 -1
  29. package/dist/fee/feeConfigMapping.js +1 -0
  30. package/dist/fee/feeConfigMapping.js.map +1 -1
  31. package/dist/fee/types.d.ts +147 -646
  32. package/dist/fee/types.d.ts.map +1 -1
  33. package/dist/fee/types.js +26 -17
  34. package/dist/fee/types.js.map +1 -1
  35. package/dist/fork/types.d.ts +125 -1924
  36. package/dist/fork/types.d.ts.map +1 -1
  37. package/dist/fork/types.js +3 -3
  38. package/dist/fork/types.js.map +1 -1
  39. package/dist/gas/oracle/types.d.ts +5 -56
  40. package/dist/gas/oracle/types.d.ts.map +1 -1
  41. package/dist/hook/EvmHookModule.d.ts.map +1 -1
  42. package/dist/hook/EvmHookModule.hardhat-test.js +12 -1
  43. package/dist/hook/EvmHookModule.hardhat-test.js.map +1 -1
  44. package/dist/hook/EvmHookModule.js +3 -0
  45. package/dist/hook/EvmHookModule.js.map +1 -1
  46. package/dist/hook/HyperlaneHookDeployer.d.ts +12 -0
  47. package/dist/hook/HyperlaneHookDeployer.d.ts.map +1 -1
  48. package/dist/hook/HyperlaneHookDeployer.hardhat-test.d.ts +2 -0
  49. package/dist/hook/HyperlaneHookDeployer.hardhat-test.d.ts.map +1 -0
  50. package/dist/hook/HyperlaneHookDeployer.hardhat-test.js +322 -0
  51. package/dist/hook/HyperlaneHookDeployer.hardhat-test.js.map +1 -0
  52. package/dist/hook/HyperlaneHookDeployer.js +262 -5
  53. package/dist/hook/HyperlaneHookDeployer.js.map +1 -1
  54. package/dist/hook/types.d.ts +44 -319
  55. package/dist/hook/types.d.ts.map +1 -1
  56. package/dist/hook/types.js +18 -11
  57. package/dist/hook/types.js.map +1 -1
  58. package/dist/ica/types.d.ts +35 -900
  59. package/dist/ica/types.d.ts.map +1 -1
  60. package/dist/ica/types.js +1 -1
  61. package/dist/ica/types.js.map +1 -1
  62. package/dist/index.d.ts +1 -1
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +1 -1
  65. package/dist/index.js.map +1 -1
  66. package/dist/ism/EvmIsmModule.d.ts +1 -1
  67. package/dist/ism/EvmIsmModule.d.ts.map +1 -1
  68. package/dist/ism/EvmIsmModule.hardhat-test.js +35 -1
  69. package/dist/ism/EvmIsmModule.hardhat-test.js.map +1 -1
  70. package/dist/ism/EvmIsmModule.js +15 -11
  71. package/dist/ism/EvmIsmModule.js.map +1 -1
  72. package/dist/ism/HyperlaneIsmFactory.d.ts +3 -1
  73. package/dist/ism/HyperlaneIsmFactory.d.ts.map +1 -1
  74. package/dist/ism/HyperlaneIsmFactory.hardhat-test.js +61 -3
  75. package/dist/ism/HyperlaneIsmFactory.hardhat-test.js.map +1 -1
  76. package/dist/ism/HyperlaneIsmFactory.js +42 -6
  77. package/dist/ism/HyperlaneIsmFactory.js.map +1 -1
  78. package/dist/ism/types.d.ts +48 -330
  79. package/dist/ism/types.d.ts.map +1 -1
  80. package/dist/ism/types.js +8 -10
  81. package/dist/ism/types.js.map +1 -1
  82. package/dist/metadata/agentConfig.d.ts +537 -10384
  83. package/dist/metadata/agentConfig.d.ts.map +1 -1
  84. package/dist/metadata/agentConfig.js +14 -16
  85. package/dist/metadata/agentConfig.js.map +1 -1
  86. package/dist/metadata/chainMetadataTypes.d.ts +70 -4678
  87. package/dist/metadata/chainMetadataTypes.d.ts.map +1 -1
  88. package/dist/metadata/chainMetadataTypes.js +5 -5
  89. package/dist/metadata/chainMetadataTypes.js.map +1 -1
  90. package/dist/metadata/customZodTypes.d.ts +5 -5
  91. package/dist/metadata/customZodTypes.d.ts.map +1 -1
  92. package/dist/metadata/customZodTypes.js +4 -5
  93. package/dist/metadata/customZodTypes.js.map +1 -1
  94. package/dist/metadata/deploymentArtifacts.d.ts +1 -13
  95. package/dist/metadata/deploymentArtifacts.d.ts.map +1 -1
  96. package/dist/metadata/matchingList.d.ts +12 -40
  97. package/dist/metadata/matchingList.d.ts.map +1 -1
  98. package/dist/metadata/warpRouteConfig.d.ts +8 -114
  99. package/dist/metadata/warpRouteConfig.d.ts.map +1 -1
  100. package/dist/metadata/warpRouteConfig.js +3 -3
  101. package/dist/metadata/warpRouteConfig.js.map +1 -1
  102. package/dist/middleware/account/InterchainAccount.d.ts.map +1 -1
  103. package/dist/middleware/account/InterchainAccount.js +12 -8
  104. package/dist/middleware/account/InterchainAccount.js.map +1 -1
  105. package/dist/middleware/account/InterchainAccount.test.js +22 -3
  106. package/dist/middleware/account/InterchainAccount.test.js.map +1 -1
  107. package/dist/middleware/account/icaCalls.d.ts +13 -145
  108. package/dist/middleware/account/icaCalls.d.ts.map +1 -1
  109. package/dist/middleware/account/types.d.ts +11 -105
  110. package/dist/middleware/account/types.d.ts.map +1 -1
  111. package/dist/predicate/PredicateApiClient.d.ts +1 -11
  112. package/dist/predicate/PredicateApiClient.d.ts.map +1 -1
  113. package/dist/providers/MultiProvider.d.ts.map +1 -1
  114. package/dist/providers/MultiProvider.js +3 -2
  115. package/dist/providers/MultiProvider.js.map +1 -1
  116. package/dist/providers/transactions/submitter/builder/types.d.ts +13 -280
  117. package/dist/providers/transactions/submitter/builder/types.d.ts.map +1 -1
  118. package/dist/providers/transactions/submitter/builder/types.js +2 -4
  119. package/dist/providers/transactions/submitter/builder/types.js.map +1 -1
  120. package/dist/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.d.ts +2 -0
  121. package/dist/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.d.ts.map +1 -1
  122. package/dist/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.js +15 -7
  123. package/dist/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.js.map +1 -1
  124. package/dist/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.test.d.ts +2 -0
  125. package/dist/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.test.d.ts.map +1 -0
  126. package/dist/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.test.js +145 -0
  127. package/dist/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.test.js.map +1 -0
  128. package/dist/providers/transactions/submitter/ethersV5/types.d.ts +30 -102
  129. package/dist/providers/transactions/submitter/ethersV5/types.d.ts.map +1 -1
  130. package/dist/providers/transactions/submitter/ethersV5/types.js +3 -21
  131. package/dist/providers/transactions/submitter/ethersV5/types.js.map +1 -1
  132. package/dist/providers/transactions/submitter/types.d.ts +5 -51
  133. package/dist/providers/transactions/submitter/types.d.ts.map +1 -1
  134. package/dist/providers/transactions/types.d.ts +1 -9
  135. package/dist/providers/transactions/types.d.ts.map +1 -1
  136. package/dist/router/types.d.ts +33 -819
  137. package/dist/router/types.d.ts.map +1 -1
  138. package/dist/router/types.js +4 -4
  139. package/dist/router/types.js.map +1 -1
  140. package/dist/rpc/evm/EvmEventLogsReader.d.ts +19 -27
  141. package/dist/rpc/evm/EvmEventLogsReader.d.ts.map +1 -1
  142. package/dist/rpc/evm/EvmEventLogsReader.js +23 -0
  143. package/dist/rpc/evm/EvmEventLogsReader.js.map +1 -1
  144. package/dist/rpc/evm/EvmEventLogsReader.test.js +53 -1
  145. package/dist/rpc/evm/EvmEventLogsReader.test.js.map +1 -1
  146. package/dist/signers/turnkeyClient.d.ts +1 -15
  147. package/dist/signers/turnkeyClient.d.ts.map +1 -1
  148. package/dist/timelock/types.d.ts +8 -32
  149. package/dist/timelock/types.d.ts.map +1 -1
  150. package/dist/token/EvmWarpRouteReader.d.ts.map +1 -1
  151. package/dist/token/EvmWarpRouteReader.js +36 -19
  152. package/dist/token/EvmWarpRouteReader.js.map +1 -1
  153. package/dist/token/EvmWarpRouteReader.test.js +219 -2
  154. package/dist/token/EvmWarpRouteReader.test.js.map +1 -1
  155. package/dist/token/EvmXERC20Reader.d.ts +9 -21
  156. package/dist/token/EvmXERC20Reader.d.ts.map +1 -1
  157. package/dist/token/EvmXERC20Reader.js +24 -48
  158. package/dist/token/EvmXERC20Reader.js.map +1 -1
  159. package/dist/token/EvmXERC20Reader.test.js +97 -0
  160. package/dist/token/EvmXERC20Reader.test.js.map +1 -1
  161. package/dist/token/ITokenMetadata.d.ts +12 -130
  162. package/dist/token/ITokenMetadata.d.ts.map +1 -1
  163. package/dist/token/ITokenMetadata.js +2 -2
  164. package/dist/token/ITokenMetadata.js.map +1 -1
  165. package/dist/token/TokenConnection.d.ts +3 -35
  166. package/dist/token/TokenConnection.d.ts.map +1 -1
  167. package/dist/token/configUtils.d.ts.map +1 -1
  168. package/dist/token/configUtils.js +16 -0
  169. package/dist/token/configUtils.js.map +1 -1
  170. package/dist/token/configUtils.test.js +57 -10
  171. package/dist/token/configUtils.test.js.map +1 -1
  172. package/dist/token/deploy.hardhat-test.js +165 -5
  173. package/dist/token/deploy.hardhat-test.js.map +1 -1
  174. package/dist/token/types.d.ts +4012 -22806
  175. package/dist/token/types.d.ts.map +1 -1
  176. package/dist/token/types.js +10 -12
  177. package/dist/token/types.js.map +1 -1
  178. package/dist/token/xerc20-abi.d.ts +31 -0
  179. package/dist/token/xerc20-abi.d.ts.map +1 -1
  180. package/dist/token/xerc20-abi.js +40 -0
  181. package/dist/token/xerc20-abi.js.map +1 -1
  182. package/dist/token/xerc20-limits.d.ts +63 -0
  183. package/dist/token/xerc20-limits.d.ts.map +1 -0
  184. package/dist/token/xerc20-limits.js +80 -0
  185. package/dist/token/xerc20-limits.js.map +1 -0
  186. package/dist/token/xerc20.d.ts +30 -1
  187. package/dist/token/xerc20.d.ts.map +1 -1
  188. package/dist/token/xerc20.js +137 -54
  189. package/dist/token/xerc20.js.map +1 -1
  190. package/dist/token/xerc20.test.js +461 -169
  191. package/dist/token/xerc20.test.js.map +1 -1
  192. package/dist/types.d.ts +6 -36
  193. package/dist/types.d.ts.map +1 -1
  194. package/dist/types.js +1 -1
  195. package/dist/types.js.map +1 -1
  196. package/dist/utils/cosmos.d.ts +113 -844
  197. package/dist/utils/cosmos.d.ts.map +1 -1
  198. package/dist/utils/cosmos.js +50 -91
  199. package/dist/utils/cosmos.js.map +1 -1
  200. package/dist/utils/schemas.d.ts +3 -3
  201. package/dist/utils/schemas.d.ts.map +1 -1
  202. package/dist/utils/schemas.js +2 -1
  203. package/dist/utils/schemas.js.map +1 -1
  204. package/dist/warp/types.d.ts +25 -367
  205. package/dist/warp/types.d.ts.map +1 -1
  206. package/package.json +11 -11
@@ -0,0 +1,322 @@
1
+ import chai, { expect } from 'chai';
2
+ import chaiAsPromised from 'chai-as-promised';
3
+ import hre from 'hardhat';
4
+ import { DomainRoutingHook__factory, FallbackDomainRoutingHook__factory, PausableHook__factory, StaticAggregationHook__factory, } from '@hyperlane-xyz/core';
5
+ import { eqAddress } from '@hyperlane-xyz/utils';
6
+ import { TestChainName } from '../consts/testChains.js';
7
+ import { TestCoreDeployer } from '../core/TestCoreDeployer.js';
8
+ import { HyperlaneProxyFactoryDeployer } from '../deploy/HyperlaneProxyFactoryDeployer.js';
9
+ import { HyperlaneIsmFactory } from '../ism/HyperlaneIsmFactory.js';
10
+ import { MultiProvider } from '../providers/MultiProvider.js';
11
+ import { HyperlaneHookDeployer } from './HyperlaneHookDeployer.js';
12
+ import { HookType, } from './types.js';
13
+ chai.use(chaiAsPromised);
14
+ describe('HyperlaneHookDeployer recovered hooks', () => {
15
+ const chain = TestChainName.test1;
16
+ const remote = TestChainName.test2;
17
+ const newRemote = TestChainName.test3;
18
+ async function deployFixture(pausablePaused = false, transferPausableOwnership = false) {
19
+ const [signer, newOwner, overrideOwner] = await hre.ethers.getSigners();
20
+ const multiProvider = MultiProvider.createTestMultiProvider({ signer });
21
+ const proxyFactoryContracts = await new HyperlaneProxyFactoryDeployer(multiProvider).deploy(multiProvider.mapKnownChains(() => ({})));
22
+ const ismFactory = new HyperlaneIsmFactory(proxyFactoryContracts, multiProvider);
23
+ const coreApp = await new TestCoreDeployer(multiProvider, ismFactory).deployApp();
24
+ const core = coreApp.getContracts(chain);
25
+ const coreAddresses = {
26
+ mailbox: core.mailbox.address,
27
+ proxyAdmin: core.proxyAdmin.address,
28
+ };
29
+ const hookDeployer = new HyperlaneHookDeployer(multiProvider, { [chain]: coreAddresses }, ismFactory);
30
+ const owner = await signer.getAddress();
31
+ const pausableOwner = transferPausableOwnership
32
+ ? await newOwner.getAddress()
33
+ : owner;
34
+ const initialConfig = {
35
+ type: HookType.FALLBACK_ROUTING,
36
+ owner,
37
+ fallback: { type: HookType.MERKLE_TREE },
38
+ domains: {
39
+ [remote]: {
40
+ type: HookType.AGGREGATION,
41
+ hooks: [
42
+ {
43
+ type: HookType.PAUSABLE,
44
+ owner: pausableOwner,
45
+ paused: pausablePaused,
46
+ },
47
+ { type: HookType.MERKLE_TREE },
48
+ ],
49
+ },
50
+ },
51
+ };
52
+ const deployed = await hookDeployer.deployContracts(chain, initialConfig, coreAddresses);
53
+ const fallbackRoutingHook = FallbackDomainRoutingHook__factory.connect(deployed.fallbackRoutingHook.address, signer);
54
+ const aggregationAddress = await fallbackRoutingHook.hooks(multiProvider.getDomainId(remote));
55
+ const pausableAddress = hookDeployer.deployedContracts[chain].pausableHook.address;
56
+ const merkleTreeAddress = hookDeployer.deployedContracts[chain].merkleTreeHook.address;
57
+ const aggregation = StaticAggregationHook__factory.connect(aggregationAddress, signer);
58
+ const childrenBefore = await aggregation.hooks(hre.ethers.constants.AddressZero);
59
+ return {
60
+ signer,
61
+ newOwner,
62
+ overrideOwner,
63
+ multiProvider,
64
+ coreApp,
65
+ coreAddresses,
66
+ hookDeployer,
67
+ owner,
68
+ pausableOwner,
69
+ fallbackRoutingHook,
70
+ aggregationAddress,
71
+ pausableAddress,
72
+ merkleTreeAddress,
73
+ aggregation,
74
+ childrenBefore,
75
+ };
76
+ }
77
+ it('applies pausable hook state before transferring ownership', async () => {
78
+ const { signer, pausableAddress, pausableOwner } = await deployFixture(true, true);
79
+ const pausable = PausableHook__factory.connect(pausableAddress, signer);
80
+ expect(await pausable.paused()).to.be.true;
81
+ expect(eqAddress(await pausable.owner(), pausableOwner)).to.be.true;
82
+ });
83
+ it('reconciles a nested recovered pausable hook without replacing the tree', async () => {
84
+ const { signer, newOwner, overrideOwner, multiProvider, coreAddresses, hookDeployer, owner, fallbackRoutingHook, aggregationAddress, pausableAddress, merkleTreeAddress, aggregation, childrenBefore, } = await deployFixture();
85
+ const recoveredPausable = {
86
+ type: HookType.PAUSABLE,
87
+ address: pausableAddress,
88
+ owner: await newOwner.getAddress(),
89
+ ownerOverrides: {
90
+ [HookType.PAUSABLE]: await overrideOwner.getAddress(),
91
+ },
92
+ paused: false,
93
+ };
94
+ const recoveredAggregation = {
95
+ type: HookType.AGGREGATION,
96
+ address: aggregationAddress,
97
+ hooks: [recoveredPausable, merkleTreeAddress],
98
+ };
99
+ const mismatchedAggregation = {
100
+ ...recoveredAggregation,
101
+ hooks: [recoveredPausable, owner],
102
+ };
103
+ const mismatchedConfig = {
104
+ type: HookType.FALLBACK_ROUTING,
105
+ address: fallbackRoutingHook.address,
106
+ owner,
107
+ fallback: merkleTreeAddress,
108
+ domains: { [remote]: mismatchedAggregation },
109
+ };
110
+ const nonceBeforeMismatch = await signer.getTransactionCount();
111
+ await expect(hookDeployer.deployContracts(chain, mismatchedConfig, coreAddresses)).to.be.rejectedWith('does not contain the configured children');
112
+ expect(await signer.getTransactionCount()).to.equal(nonceBeforeMismatch);
113
+ const unchangedPausable = PausableHook__factory.connect(pausableAddress, signer);
114
+ expect(await unchangedPausable.paused()).to.be.false;
115
+ expect(eqAddress(await unchangedPausable.owner(), owner)).to.be.true;
116
+ const pauseMismatch = {
117
+ type: HookType.FALLBACK_ROUTING,
118
+ address: fallbackRoutingHook.address,
119
+ owner,
120
+ fallback: merkleTreeAddress,
121
+ domains: {
122
+ [remote]: {
123
+ ...recoveredAggregation,
124
+ hooks: [{ ...recoveredPausable, paused: true }, merkleTreeAddress],
125
+ },
126
+ },
127
+ };
128
+ await expect(hookDeployer.deployContracts(chain, pauseMismatch, coreAddresses)).to.be.rejectedWith('but config expects paused');
129
+ expect(await signer.getTransactionCount()).to.equal(nonceBeforeMismatch);
130
+ const invalidLaterChild = {
131
+ type: HookType.FALLBACK_ROUTING,
132
+ address: fallbackRoutingHook.address,
133
+ owner,
134
+ fallback: merkleTreeAddress,
135
+ domains: {
136
+ [remote]: recoveredAggregation,
137
+ [newRemote]: {
138
+ type: HookType.AGGREGATION,
139
+ address: merkleTreeAddress,
140
+ hooks: [],
141
+ },
142
+ },
143
+ };
144
+ await expect(hookDeployer.deployContracts(chain, invalidLaterChild, coreAddresses)).to.be.rejectedWith('has type');
145
+ expect(await signer.getTransactionCount()).to.equal(nonceBeforeMismatch);
146
+ expect(eqAddress(await unchangedPausable.owner(), owner)).to.be.true;
147
+ const conflictingAggregation = {
148
+ ...recoveredAggregation,
149
+ hooks: [
150
+ { ...recoveredPausable, owner: await overrideOwner.getAddress() },
151
+ merkleTreeAddress,
152
+ ],
153
+ };
154
+ const conflictingAliases = {
155
+ type: HookType.FALLBACK_ROUTING,
156
+ address: fallbackRoutingHook.address,
157
+ owner,
158
+ fallback: merkleTreeAddress,
159
+ domains: {
160
+ [remote]: recoveredAggregation,
161
+ [newRemote]: conflictingAggregation,
162
+ },
163
+ };
164
+ await expect(hookDeployer.deployContracts(chain, conflictingAliases, coreAddresses)).to.be.rejectedWith('has conflicting configs');
165
+ expect(await signer.getTransactionCount()).to.equal(nonceBeforeMismatch);
166
+ const recoveredConfig = {
167
+ type: HookType.FALLBACK_ROUTING,
168
+ address: fallbackRoutingHook.address,
169
+ owner,
170
+ fallback: merkleTreeAddress,
171
+ domains: {
172
+ [remote]: recoveredAggregation,
173
+ [newRemote]: recoveredAggregation,
174
+ },
175
+ };
176
+ const nonceBefore = await signer.getTransactionCount();
177
+ const recovered = await hookDeployer.deployContracts(chain, recoveredConfig, coreAddresses);
178
+ const nonceAfter = await signer.getTransactionCount();
179
+ expect(recovered.fallbackRoutingHook.address).to.equal(fallbackRoutingHook.address);
180
+ // transferOwnership on the recovered pausable, then one setHooks call to
181
+ // enroll newRemote with the existing aggregation.
182
+ expect(nonceAfter - nonceBefore).to.equal(2);
183
+ expect(eqAddress(await fallbackRoutingHook.hooks(multiProvider.getDomainId(remote)), aggregationAddress)).to.be.true;
184
+ expect(eqAddress(await fallbackRoutingHook.hooks(multiProvider.getDomainId(newRemote)), aggregationAddress)).to.be.true;
185
+ const childrenAfter = await aggregation.hooks(hre.ethers.constants.AddressZero);
186
+ expect(childrenAfter).to.deep.equal(childrenBefore);
187
+ const pausable = PausableHook__factory.connect(pausableAddress, signer);
188
+ expect(await pausable.paused()).to.be.false;
189
+ expect(eqAddress(await pausable.owner(), await overrideOwner.getAddress()))
190
+ .to.be.true;
191
+ });
192
+ it('rejects recovery when the signer does not own a mutable hook', async () => {
193
+ const { signer, newOwner, overrideOwner, multiProvider, coreAddresses, hookDeployer, owner, fallbackRoutingHook, aggregationAddress, pausableAddress, merkleTreeAddress, } = await deployFixture();
194
+ multiProvider.setSharedSigner(overrideOwner);
195
+ const pausable = PausableHook__factory.connect(pausableAddress, signer);
196
+ const pausableOwnerBefore = await pausable.owner();
197
+ const pausablePausedBefore = await pausable.paused();
198
+ const nonceBeforePausable = await overrideOwner.getTransactionCount();
199
+ const recoveredPausable = {
200
+ type: HookType.PAUSABLE,
201
+ address: pausableAddress,
202
+ owner: await newOwner.getAddress(),
203
+ paused: false,
204
+ };
205
+ await expect(hookDeployer.deployContracts(chain, recoveredPausable, coreAddresses)).to.be.rejectedWith('is not owner');
206
+ expect(await overrideOwner.getTransactionCount()).to.equal(nonceBeforePausable);
207
+ expect(await pausable.owner()).to.equal(pausableOwnerBefore);
208
+ expect(await pausable.paused()).to.equal(pausablePausedBefore);
209
+ const routingOwnerBefore = await fallbackRoutingHook.owner();
210
+ const remoteHookBefore = await fallbackRoutingHook.hooks(multiProvider.getDomainId(remote));
211
+ const nonceBeforeRouting = await overrideOwner.getTransactionCount();
212
+ const recoveredRouting = {
213
+ type: HookType.FALLBACK_ROUTING,
214
+ address: fallbackRoutingHook.address,
215
+ owner: await newOwner.getAddress(),
216
+ fallback: merkleTreeAddress,
217
+ domains: { [remote]: aggregationAddress },
218
+ };
219
+ await expect(hookDeployer.deployContracts(chain, recoveredRouting, coreAddresses)).to.be.rejectedWith('is not owner');
220
+ expect(await overrideOwner.getTransactionCount()).to.equal(nonceBeforeRouting);
221
+ expect(await fallbackRoutingHook.owner()).to.equal(routingOwnerBefore);
222
+ expect(await fallbackRoutingHook.hooks(multiProvider.getDomainId(remote))).to.equal(remoteHookBefore);
223
+ expect(eqAddress(routingOwnerBefore, owner)).to.be.true;
224
+ });
225
+ it('validates recovered hook mailboxes, including nested hooks', async () => {
226
+ const { signer, newOwner, multiProvider, coreApp, coreAddresses, hookDeployer, owner, fallbackRoutingHook, aggregationAddress, merkleTreeAddress, } = await deployFixture();
227
+ const wrongCoreAddresses = {
228
+ ...coreAddresses,
229
+ mailbox: await newOwner.getAddress(),
230
+ };
231
+ const nonceBefore = await signer.getTransactionCount();
232
+ const recoveredMerkleTree = {
233
+ type: HookType.MERKLE_TREE,
234
+ address: merkleTreeAddress,
235
+ };
236
+ await expect(hookDeployer.deployContracts(chain, recoveredMerkleTree, wrongCoreAddresses)).to.be.rejectedWith('has mailbox');
237
+ const recoveredFallback = {
238
+ type: HookType.FALLBACK_ROUTING,
239
+ address: fallbackRoutingHook.address,
240
+ owner,
241
+ fallback: merkleTreeAddress,
242
+ domains: { [remote]: aggregationAddress },
243
+ };
244
+ await expect(hookDeployer.deployContracts(chain, recoveredFallback, wrongCoreAddresses)).to.be.rejectedWith('has mailbox');
245
+ expect(await signer.getTransactionCount()).to.equal(nonceBefore);
246
+ const foreignCore = coreApp.getContracts(remote);
247
+ const foreignMerkleTreeAddress = await foreignCore.mailbox.defaultHook();
248
+ const foreignAggregation = await hookDeployer.deployContracts(chain, {
249
+ type: HookType.AGGREGATION,
250
+ hooks: [foreignMerkleTreeAddress],
251
+ }, coreAddresses);
252
+ const mixedFallback = await hookDeployer.deployContracts(chain, {
253
+ type: HookType.FALLBACK_ROUTING,
254
+ owner,
255
+ fallback: merkleTreeAddress,
256
+ domains: {
257
+ [remote]: foreignAggregation.aggregationHook.address,
258
+ },
259
+ }, coreAddresses);
260
+ const recoveredMixedFallback = {
261
+ type: HookType.FALLBACK_ROUTING,
262
+ address: mixedFallback.fallbackRoutingHook.address,
263
+ owner,
264
+ fallback: merkleTreeAddress,
265
+ domains: {
266
+ [remote]: {
267
+ type: HookType.AGGREGATION,
268
+ address: foreignAggregation.aggregationHook.address,
269
+ hooks: [
270
+ {
271
+ type: HookType.MERKLE_TREE,
272
+ address: foreignMerkleTreeAddress,
273
+ },
274
+ ],
275
+ },
276
+ },
277
+ };
278
+ const mixedFallbackHook = FallbackDomainRoutingHook__factory.connect(mixedFallback.fallbackRoutingHook.address, signer);
279
+ const mixedFallbackOwnerBefore = await mixedFallbackHook.owner();
280
+ const mixedFallbackRouteBefore = await mixedFallbackHook.hooks(multiProvider.getDomainId(remote));
281
+ const nonceBeforeNestedRecovery = await signer.getTransactionCount();
282
+ await expect(hookDeployer.deployContracts(chain, recoveredMixedFallback, coreAddresses)).to.be.rejectedWith('has mailbox');
283
+ expect(await signer.getTransactionCount()).to.equal(nonceBeforeNestedRecovery);
284
+ expect(await mixedFallbackHook.owner()).to.equal(mixedFallbackOwnerBefore);
285
+ expect(await mixedFallbackHook.hooks(multiProvider.getDomainId(remote))).to.equal(mixedFallbackRouteBefore);
286
+ });
287
+ it('reconciles a recovered routing hook without redeployment', async () => {
288
+ const { signer, newOwner, multiProvider, coreAddresses, hookDeployer, owner, merkleTreeAddress, } = await deployFixture();
289
+ const initialConfig = {
290
+ type: HookType.ROUTING,
291
+ owner,
292
+ domains: { [remote]: merkleTreeAddress },
293
+ };
294
+ const deployed = await hookDeployer.deployContracts(chain, initialConfig, coreAddresses);
295
+ const routingHook = DomainRoutingHook__factory.connect(deployed.domainRoutingHook.address, signer);
296
+ const recoveredConfig = {
297
+ ...initialConfig,
298
+ address: routingHook.address,
299
+ owner: await newOwner.getAddress(),
300
+ domains: {
301
+ [remote]: merkleTreeAddress,
302
+ [newRemote]: merkleTreeAddress,
303
+ },
304
+ };
305
+ const nonceBeforeMailboxMismatch = await signer.getTransactionCount();
306
+ await expect(hookDeployer.deployContracts(chain, recoveredConfig, {
307
+ ...coreAddresses,
308
+ mailbox: await newOwner.getAddress(),
309
+ })).to.be.rejectedWith('has mailbox');
310
+ expect(await signer.getTransactionCount()).to.equal(nonceBeforeMailboxMismatch);
311
+ expect(await routingHook.owner()).to.equal(owner);
312
+ expect(await routingHook.hooks(multiProvider.getDomainId(newRemote))).to.equal(hre.ethers.constants.AddressZero);
313
+ const nonceBefore = await signer.getTransactionCount();
314
+ const recovered = await hookDeployer.deployContracts(chain, recoveredConfig, coreAddresses);
315
+ expect((await signer.getTransactionCount()) - nonceBefore).to.equal(2);
316
+ expect(recovered.domainRoutingHook.address).to.equal(routingHook.address);
317
+ expect(await routingHook.hooks(multiProvider.getDomainId(remote))).to.equal(merkleTreeAddress);
318
+ expect(await routingHook.hooks(multiProvider.getDomainId(newRemote))).to.equal(merkleTreeAddress);
319
+ expect(await routingHook.owner()).to.equal(await newOwner.getAddress());
320
+ });
321
+ });
322
+ //# sourceMappingURL=HyperlaneHookDeployer.hardhat-test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HyperlaneHookDeployer.hardhat-test.js","sourceRoot":"","sources":["../../src/hook/HyperlaneHookDeployer.hardhat-test.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,36 @@
1
- import { CCIPHook__factory, IL1CrossDomainMessenger__factory, StaticAggregationHook__factory, } from '@hyperlane-xyz/core';
2
- import { ZERO_ADDRESS_HEX_32, addBufferToGasLimit, addressToBytes32, assert, deepEquals, rootLogger, } from '@hyperlane-xyz/utils';
1
+ import { ethers } from 'ethers';
2
+ import { CCIPHook__factory, DomainRoutingHook__factory, FallbackDomainRoutingHook__factory, IL1CrossDomainMessenger__factory, IPostDispatchHook__factory, MailboxClient__factory, MerkleTreeHook__factory, PausableHook__factory, StaticAggregationHook__factory, } from '@hyperlane-xyz/core';
3
+ import { ZERO_ADDRESS_HEX_32, addBufferToGasLimit, addressToBytes32, assert, deepEquals, eqAddress, isZeroishAddress, rootLogger, } from '@hyperlane-xyz/utils';
3
4
  import { HyperlaneDeployer } from '../deploy/HyperlaneDeployer.js';
4
- import { submitBatched } from '../deploy/utils.js';
5
+ import { getTxConfigBatchSize, submitBatched } from '../deploy/utils.js';
5
6
  import { HyperlaneIgpDeployer } from '../gas/HyperlaneIgpDeployer.js';
6
7
  import { IsmType } from '../ism/types.js';
7
8
  import { hookFactories } from './contracts.js';
8
- import { HookType, } from './types.js';
9
+ import { HookType, OnchainHookType, } from './types.js';
10
+ // Hook types that can be recovered without redeployment when the config carries
11
+ // an existing address. Mutable recovered hooks are reconciled in place, and
12
+ // recovered composites traverse only explicitly addressed children.
13
+ const RECOVERABLE_HOOK_TYPES = [
14
+ HookType.MERKLE_TREE,
15
+ HookType.AGGREGATION,
16
+ HookType.PAUSABLE,
17
+ HookType.ROUTING,
18
+ HookType.FALLBACK_ROUTING,
19
+ ];
20
+ const RECOVERABLE_ONCHAIN_HOOK_TYPES = {
21
+ [HookType.MERKLE_TREE]: OnchainHookType.MERKLE_TREE,
22
+ [HookType.AGGREGATION]: OnchainHookType.AGGREGATION,
23
+ [HookType.PAUSABLE]: OnchainHookType.PAUSABLE,
24
+ [HookType.ROUTING]: OnchainHookType.ROUTING,
25
+ [HookType.FALLBACK_ROUTING]: OnchainHookType.FALLBACK_ROUTING,
26
+ };
27
+ function configuredHookAddress(config) {
28
+ if (typeof config === 'string')
29
+ return config;
30
+ return 'address' in config && typeof config.address === 'string'
31
+ ? config.address
32
+ : undefined;
33
+ }
9
34
  export class HyperlaneHookDeployer extends HyperlaneDeployer {
10
35
  core;
11
36
  ismFactory;
@@ -28,6 +53,40 @@ export class HyperlaneHookDeployer extends HyperlaneDeployer {
28
53
  if (typeof config === 'string') {
29
54
  throw new Error('Hook deployer should not receive address config');
30
55
  }
56
+ // Configs carrying an `address` reference an already-deployed hook:
57
+ // recover the existing contract instead of deploying a new one.
58
+ const existingHookAddress = configuredHookAddress(config);
59
+ if (existingHookAddress && RECOVERABLE_HOOK_TYPES.includes(config.type)) {
60
+ const context = {
61
+ expectedMailbox: coreAddresses.mailbox,
62
+ configs: new Map(),
63
+ routingHooks: new Map(),
64
+ };
65
+ await this.validateRecoveredHook(chain, config, existingHookAddress, context);
66
+ await this.reconcileRecoveredHook(chain, config, existingHookAddress, new Set(), context);
67
+ const signerOrProvider = this.multiProvider.getSignerOrProvider(chain);
68
+ const hook = (() => {
69
+ switch (config.type) {
70
+ case HookType.MERKLE_TREE:
71
+ return MerkleTreeHook__factory.connect(existingHookAddress, signerOrProvider);
72
+ case HookType.AGGREGATION:
73
+ return StaticAggregationHook__factory.connect(existingHookAddress, signerOrProvider);
74
+ case HookType.PAUSABLE:
75
+ return PausableHook__factory.connect(existingHookAddress, signerOrProvider);
76
+ case HookType.ROUTING:
77
+ return DomainRoutingHook__factory.connect(existingHookAddress, signerOrProvider);
78
+ case HookType.FALLBACK_ROUTING:
79
+ return FallbackDomainRoutingHook__factory.connect(existingHookAddress, signerOrProvider);
80
+ default:
81
+ throw new Error(`Hook type ${config.type} cannot be recovered`);
82
+ }
83
+ })();
84
+ // CAST: deployers return the subset of HookFactories materialized by the
85
+ // requested config; HyperlaneContracts currently models a complete map.
86
+ const deployedContracts = { [config.type]: hook }; // partial
87
+ this.addDeployedContracts(chain, deployedContracts);
88
+ return deployedContracts;
89
+ }
31
90
  let hook;
32
91
  if (config.type === HookType.MERKLE_TREE ||
33
92
  config.type === HookType.MAILBOX_DEFAULT) {
@@ -56,7 +115,11 @@ export class HyperlaneHookDeployer extends HyperlaneDeployer {
56
115
  hook = await this.deployRouting(chain, config, coreAddresses);
57
116
  }
58
117
  else if (config.type === HookType.PAUSABLE) {
59
- hook = await this.deployContract(chain, config.type, []);
118
+ const pausableHook = await this.deployContract(chain, config.type, []);
119
+ if (config.paused) {
120
+ await this.multiProvider.handleTx(chain, pausableHook.pause(this.multiProvider.getTransactionOverrides(chain)));
121
+ }
122
+ hook = pausableHook;
60
123
  await this.transferOwnershipOfContracts(chain, config, {
61
124
  [HookType.PAUSABLE]: hook,
62
125
  });
@@ -74,6 +137,200 @@ export class HyperlaneHookDeployer extends HyperlaneDeployer {
74
137
  this.addDeployedContracts(chain, deployedContracts);
75
138
  return deployedContracts;
76
139
  }
140
+ recoveredOwner(config) {
141
+ const owner = config.ownerOverrides?.[config.type] ?? config.owner;
142
+ assert(!isZeroishAddress(owner), `Recovered ${config.type} owner cannot be the zero address`);
143
+ return owner;
144
+ }
145
+ addRecoveredConfig(configs, address, config) {
146
+ const key = address.toLowerCase();
147
+ const existing = configs.get(key);
148
+ assert(!existing || deepEquals(existing, config), `Recovered hook ${address} has conflicting configs`);
149
+ if (existing)
150
+ return false;
151
+ configs.set(key, config);
152
+ return true;
153
+ }
154
+ async validateRecoveredHook(chain, config, address, context) {
155
+ if (!this.addRecoveredConfig(context.configs, address, config))
156
+ return;
157
+ const expectedType = RECOVERABLE_ONCHAIN_HOOK_TYPES[config.type];
158
+ assert(expectedType !== undefined, `Hook type ${config.type} cannot be recovered by address`);
159
+ const actualType = await IPostDispatchHook__factory.connect(address, this.multiProvider.getProvider(chain)).hookType();
160
+ assert(actualType === expectedType, `Recovered hook ${address} on ${chain} has type ${actualType}, expected ${expectedType}`);
161
+ if (config.type === HookType.MERKLE_TREE ||
162
+ config.type === HookType.ROUTING ||
163
+ config.type === HookType.FALLBACK_ROUTING) {
164
+ assert(context.expectedMailbox, `Mailbox address is required to recover ${config.type}`);
165
+ const actualMailbox = await MailboxClient__factory.connect(address, this.multiProvider.getProvider(chain)).mailbox();
166
+ assert(eqAddress(actualMailbox, context.expectedMailbox), `Recovered hook ${address} on ${chain} has mailbox ${actualMailbox}, expected ${context.expectedMailbox}`);
167
+ }
168
+ switch (config.type) {
169
+ case HookType.PAUSABLE:
170
+ await this.validateRecoveredPausableHook(chain, config, address);
171
+ break;
172
+ case HookType.AGGREGATION:
173
+ await this.validateRecoveredAggregationHook(chain, config, address, context);
174
+ break;
175
+ case HookType.ROUTING:
176
+ case HookType.FALLBACK_ROUTING:
177
+ await this.validateRecoveredRoutingHook(chain, config, address, context);
178
+ break;
179
+ case HookType.MERKLE_TREE:
180
+ break;
181
+ default:
182
+ assert(false, `Hook type ${config.type} cannot be recovered by address`);
183
+ }
184
+ }
185
+ async validateRecoveredPausableHook(chain, config, address) {
186
+ const hook = PausableHook__factory.connect(address, this.multiProvider.getProvider(chain));
187
+ const [currentOwner, currentPaused, signer] = await Promise.all([
188
+ hook.owner(),
189
+ hook.paused(),
190
+ this.multiProvider.getSignerAddress(chain),
191
+ ]);
192
+ assert(currentPaused === config.paused, `Recovered pausable hook ${address} on ${chain} is ${currentPaused ? '' : 'not '}paused, but config expects ${config.paused ? '' : 'not '}paused`);
193
+ const owner = this.recoveredOwner(config);
194
+ if (!eqAddress(currentOwner, owner)) {
195
+ assert(eqAddress(currentOwner, signer), `Cannot reconcile recovered pausable hook ${address} on ${chain}: signer ${signer} is not owner ${currentOwner}`);
196
+ }
197
+ }
198
+ async validateRecoveredAggregationHook(chain, config, address, context) {
199
+ await this.assertRecoveredAggregationChildren(chain, config, address);
200
+ for (const hookConfig of config.hooks) {
201
+ if (typeof hookConfig === 'string')
202
+ continue;
203
+ const hookAddress = configuredHookAddress(hookConfig);
204
+ assert(hookAddress, 'Recovered aggregation child address is required');
205
+ await this.validateRecoveredHook(chain, hookConfig, hookAddress, context);
206
+ }
207
+ }
208
+ async validateRecoveredRoutingHook(chain, config, address, context) {
209
+ const recoveredRoutingHook = await this.readRecoveredRoutingHook(chain, config, address);
210
+ context.routingHooks.set(address.toLowerCase(), recoveredRoutingHook);
211
+ const { routingHook, routingConfigs, childConfigs } = recoveredRoutingHook;
212
+ const [currentOwner, signer] = await Promise.all([
213
+ routingHook.owner(),
214
+ this.multiProvider.getSignerAddress(chain),
215
+ ]);
216
+ const owner = this.recoveredOwner(config);
217
+ if (routingConfigs.length > 0 || !eqAddress(currentOwner, owner)) {
218
+ assert(eqAddress(currentOwner, signer), `Cannot reconcile recovered routing hook ${address} on ${chain}: signer ${signer} is not owner ${currentOwner}`);
219
+ }
220
+ const batchSize = getTxConfigBatchSize(chain);
221
+ for (let i = 0; i < routingConfigs.length; i += batchSize) {
222
+ await routingHook.estimateGas.setHooks(routingConfigs.slice(i, i + batchSize));
223
+ }
224
+ for (const [childAddress, childConfig] of childConfigs) {
225
+ await this.validateRecoveredHook(chain, childConfig, childAddress, context);
226
+ }
227
+ }
228
+ async reconcileRecoveredHook(chain, config, address, reconciled, context) {
229
+ const key = address.toLowerCase();
230
+ if (reconciled.has(key))
231
+ return;
232
+ reconciled.add(key);
233
+ switch (config.type) {
234
+ case HookType.PAUSABLE:
235
+ await this.reconcileRecoveredPausableHook(chain, config, address);
236
+ break;
237
+ case HookType.AGGREGATION:
238
+ await this.reconcileRecoveredAggregationHook(chain, config, address, reconciled, context);
239
+ break;
240
+ case HookType.ROUTING:
241
+ case HookType.FALLBACK_ROUTING:
242
+ await this.reconcileRecoveredRoutingHook(chain, config, address, reconciled, context);
243
+ break;
244
+ default:
245
+ break;
246
+ }
247
+ }
248
+ async reconcileRecoveredPausableHook(chain, config, address) {
249
+ const hook = PausableHook__factory.connect(address, this.multiProvider.getSignerOrProvider(chain));
250
+ const currentOwner = await hook.owner();
251
+ const owner = this.recoveredOwner(config);
252
+ if (eqAddress(currentOwner, owner))
253
+ return;
254
+ const overrides = this.multiProvider.getTransactionOverrides(chain);
255
+ await this.multiProvider.handleTx(chain, hook.transferOwnership(owner, overrides));
256
+ }
257
+ async assertRecoveredAggregationChildren(chain, config, address) {
258
+ const expectedAddresses = config.hooks.map((hookConfig) => {
259
+ const hookAddress = configuredHookAddress(hookConfig);
260
+ assert(hookAddress, `Recovered aggregation hook ${address} on ${chain} requires addresses for every child`);
261
+ return hookAddress;
262
+ });
263
+ const aggregation = StaticAggregationHook__factory.connect(address, this.multiProvider.getProvider(chain));
264
+ const actualAddresses = await aggregation.hooks(ethers.constants.AddressZero);
265
+ const expectedSorted = [...expectedAddresses].sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
266
+ const actualSorted = [...actualAddresses].sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
267
+ assert(actualSorted.length === expectedSorted.length &&
268
+ actualSorted.every((hookAddress, index) => eqAddress(hookAddress, expectedSorted[index])), `Recovered aggregation hook ${address} on ${chain} does not contain the configured children`);
269
+ }
270
+ async reconcileRecoveredAggregationHook(chain, config, address, reconciled, context) {
271
+ for (const hookConfig of config.hooks) {
272
+ if (typeof hookConfig === 'string')
273
+ continue;
274
+ const hookAddress = configuredHookAddress(hookConfig);
275
+ assert(hookAddress, 'Recovered aggregation child address is required');
276
+ await this.reconcileRecoveredHook(chain, hookConfig, hookAddress, reconciled, context);
277
+ }
278
+ }
279
+ async readRecoveredRoutingHook(chain, config, address) {
280
+ let routingHook;
281
+ const childConfigs = new Map();
282
+ if (config.type === HookType.FALLBACK_ROUTING) {
283
+ const fallbackRoutingHook = FallbackDomainRoutingHook__factory.connect(address, this.multiProvider.getSignerOrProvider(chain));
284
+ routingHook = fallbackRoutingHook;
285
+ const fallbackAddress = configuredHookAddress(config.fallback);
286
+ assert(fallbackAddress, `Recovered fallback routing hook ${address} on ${chain} requires a fallback address`);
287
+ const actualFallback = await fallbackRoutingHook.fallbackHook();
288
+ assert(eqAddress(actualFallback, fallbackAddress), `Recovered fallback routing hook ${address} on ${chain} has fallback ${actualFallback}, expected ${fallbackAddress}`);
289
+ if (typeof config.fallback !== 'string') {
290
+ this.addRecoveredConfig(childConfigs, fallbackAddress, config.fallback);
291
+ }
292
+ }
293
+ else {
294
+ routingHook = DomainRoutingHook__factory.connect(address, this.multiProvider.getSignerOrProvider(chain));
295
+ }
296
+ const domainConfigs = Object.entries(config.domains).map(([destination, hookConfig]) => {
297
+ const hookAddress = configuredHookAddress(hookConfig);
298
+ assert(hookAddress, `Recovered routing hook ${address} on ${chain} requires an address for ${destination}`);
299
+ if (typeof hookConfig !== 'string') {
300
+ this.addRecoveredConfig(childConfigs, hookAddress, hookConfig);
301
+ }
302
+ return {
303
+ destination: this.multiProvider.getDomainId(destination),
304
+ hook: hookAddress,
305
+ };
306
+ });
307
+ const actualHooks = await Promise.all(domainConfigs.map(({ destination }) => routingHook.hooks(destination)));
308
+ const routingConfigs = domainConfigs.filter(({ hook }, index) => !eqAddress(actualHooks[index], hook));
309
+ return { routingHook, routingConfigs, childConfigs };
310
+ }
311
+ async reconcileRecoveredRoutingHook(chain, config, address, reconciled, context) {
312
+ const recoveredRoutingHook = context.routingHooks.get(address.toLowerCase());
313
+ assert(recoveredRoutingHook, `Recovered routing hook ${address} on ${chain} was not validated`);
314
+ const { routingHook, routingConfigs, childConfigs } = recoveredRoutingHook;
315
+ for (const [childAddress, childConfig] of childConfigs) {
316
+ await this.reconcileRecoveredHook(chain, childConfig, childAddress, reconciled, context);
317
+ }
318
+ const overrides = this.multiProvider.getTransactionOverrides(chain);
319
+ if (routingConfigs.length > 0) {
320
+ await submitBatched(chain, routingConfigs, async (batch) => {
321
+ const estimatedGas = await routingHook.estimateGas.setHooks(batch);
322
+ await this.multiProvider.handleTx(chain, routingHook.setHooks(batch, {
323
+ gasLimit: addBufferToGasLimit(estimatedGas),
324
+ ...overrides,
325
+ }));
326
+ }, this.logger, 'recovered routing hook configs');
327
+ }
328
+ const owner = this.recoveredOwner(config);
329
+ const currentOwner = await routingHook.owner();
330
+ if (!eqAddress(currentOwner, owner)) {
331
+ await this.multiProvider.handleTx(chain, routingHook.transferOwnership(owner, overrides));
332
+ }
333
+ }
77
334
  async deployCCIPHook(chain, config) {
78
335
  const hook = this.ismFactory.ccipContractCache.getHook(chain, config.destinationChain);
79
336
  if (!hook) {