@humanode-hyperlane/deploy-sdk 0.0.0-stage → 4.2.3

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 (79) hide show
  1. package/LICENSE.md +193 -0
  2. package/dist/AltVMFileSubmitter.d.ts +12 -0
  3. package/dist/AltVMFileSubmitter.d.ts.map +1 -0
  4. package/dist/AltVMFileSubmitter.js +35 -0
  5. package/dist/AltVMFileSubmitter.js.map +1 -0
  6. package/dist/AltVMJsonRpcSubmitter.d.ts +16 -0
  7. package/dist/AltVMJsonRpcSubmitter.d.ts.map +1 -0
  8. package/dist/AltVMJsonRpcSubmitter.js +40 -0
  9. package/dist/AltVMJsonRpcSubmitter.js.map +1 -0
  10. package/dist/core/core-artifact-reader.d.ts +67 -0
  11. package/dist/core/core-artifact-reader.d.ts.map +1 -0
  12. package/dist/core/core-artifact-reader.js +117 -0
  13. package/dist/core/core-artifact-reader.js.map +1 -0
  14. package/dist/core/core-artifact-reader.test.d.ts +2 -0
  15. package/dist/core/core-artifact-reader.test.d.ts.map +1 -0
  16. package/dist/core/core-artifact-reader.test.js +300 -0
  17. package/dist/core/core-artifact-reader.test.js.map +1 -0
  18. package/dist/core/core-writer.d.ts +43 -0
  19. package/dist/core/core-writer.d.ts.map +1 -0
  20. package/dist/core/core-writer.js +235 -0
  21. package/dist/core/core-writer.js.map +1 -0
  22. package/dist/core/core-writer.test.d.ts +2 -0
  23. package/dist/core/core-writer.test.d.ts.map +1 -0
  24. package/dist/core/core-writer.test.js +1097 -0
  25. package/dist/core/core-writer.test.js.map +1 -0
  26. package/dist/hook/hook-reader.d.ts +41 -0
  27. package/dist/hook/hook-reader.d.ts.map +1 -0
  28. package/dist/hook/hook-reader.js +52 -0
  29. package/dist/hook/hook-reader.js.map +1 -0
  30. package/dist/hook/hook-writer.d.ts +101 -0
  31. package/dist/hook/hook-writer.d.ts.map +1 -0
  32. package/dist/hook/hook-writer.js +140 -0
  33. package/dist/hook/hook-writer.js.map +1 -0
  34. package/dist/hook/hook-writer.test.d.ts +2 -0
  35. package/dist/hook/hook-writer.test.d.ts.map +1 -0
  36. package/dist/hook/hook-writer.test.js +69 -0
  37. package/dist/hook/hook-writer.test.js.map +1 -0
  38. package/dist/index.d.ts +12 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +15 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/ism/generic-ism-writer.d.ts +61 -0
  43. package/dist/ism/generic-ism-writer.d.ts.map +1 -0
  44. package/dist/ism/generic-ism-writer.js +84 -0
  45. package/dist/ism/generic-ism-writer.js.map +1 -0
  46. package/dist/ism/generic-ism.d.ts +43 -0
  47. package/dist/ism/generic-ism.d.ts.map +1 -0
  48. package/dist/ism/generic-ism.js +95 -0
  49. package/dist/ism/generic-ism.js.map +1 -0
  50. package/dist/ism/routing-ism.d.ts +21 -0
  51. package/dist/ism/routing-ism.d.ts.map +1 -0
  52. package/dist/ism/routing-ism.js +145 -0
  53. package/dist/ism/routing-ism.js.map +1 -0
  54. package/dist/protocol.d.ts +3 -0
  55. package/dist/protocol.d.ts.map +1 -0
  56. package/dist/protocol.js +38 -0
  57. package/dist/protocol.js.map +1 -0
  58. package/dist/protocol.test.d.ts +2 -0
  59. package/dist/protocol.test.d.ts.map +1 -0
  60. package/dist/protocol.test.js +14 -0
  61. package/dist/protocol.test.js.map +1 -0
  62. package/dist/utils/validation.d.ts +37 -0
  63. package/dist/utils/validation.d.ts.map +1 -0
  64. package/dist/utils/validation.js +66 -0
  65. package/dist/utils/validation.js.map +1 -0
  66. package/dist/warp/warp-reader.d.ts +49 -0
  67. package/dist/warp/warp-reader.d.ts.map +1 -0
  68. package/dist/warp/warp-reader.js +108 -0
  69. package/dist/warp/warp-reader.js.map +1 -0
  70. package/dist/warp/warp-writer.d.ts +66 -0
  71. package/dist/warp/warp-writer.d.ts.map +1 -0
  72. package/dist/warp/warp-writer.js +231 -0
  73. package/dist/warp/warp-writer.js.map +1 -0
  74. package/dist/warp/warp-writer.test.d.ts +2 -0
  75. package/dist/warp/warp-writer.test.d.ts.map +1 -0
  76. package/dist/warp/warp-writer.test.js +903 -0
  77. package/dist/warp/warp-writer.test.js.map +1 -0
  78. package/package.json +48 -3
  79. package/README.md +0 -3
@@ -0,0 +1,1097 @@
1
+ import { expect } from 'chai';
2
+ import sinon from 'sinon';
3
+ import { MockSigner, hasProtocol, registerProtocol, } from '@humanode-hyperlane/provider-sdk';
4
+ import { ArtifactState, } from '@humanode-hyperlane/provider-sdk/artifact';
5
+ import { ProtocolType, } from '@humanode-hyperlane/provider-sdk/protocol';
6
+ import { ZERO_ADDRESS_HEX_32 } from '@humanode-hyperlane/utils';
7
+ import { CoreWriter } from './core-writer.js';
8
+ // Test protocol
9
+ const TestProtocol = 'test-core-writer';
10
+ let mockIsmArtifactManager;
11
+ let mockHookArtifactManager;
12
+ let mockProtocolProvider;
13
+ if (!hasProtocol(TestProtocol)) {
14
+ registerProtocol(TestProtocol, () => mockProtocolProvider);
15
+ }
16
+ if (!hasProtocol(ProtocolType.Starknet)) {
17
+ registerProtocol(ProtocolType.Starknet, () => mockProtocolProvider);
18
+ }
19
+ describe('CoreWriter', () => {
20
+ const mockMailboxAddress = '0xMAILBOX';
21
+ const mockIsmAddress = '0xISM';
22
+ const mockNewIsmAddress = '0xNEWISM';
23
+ const mockDefaultHookAddress = '0xDEFAULTHOOK';
24
+ const mockRequiredHookAddress = '0xREQUIREDHOOK';
25
+ const mockValidatorAnnounceAddress = '0xVA';
26
+ const mockOwner = '0xOWNER';
27
+ const mockSignerAddress = '0xSIGNER';
28
+ const mockDomainId = 1;
29
+ const chainName = 'test-chain';
30
+ let createMailboxWriterStub;
31
+ let createVAWriterStub;
32
+ let getSignerAddressStub;
33
+ let sendAndConfirmTxStub;
34
+ let mailboxArtifactManager;
35
+ let validatorAnnounceArtifactManager;
36
+ let signer;
37
+ let chainLookup;
38
+ let chainMetadata;
39
+ let coreWriter;
40
+ const mockReceipt = {
41
+ transactionHash: '0xHASH',
42
+ blockNumber: 123,
43
+ };
44
+ const mockIsm = {
45
+ artifactState: ArtifactState.DEPLOYED,
46
+ config: {
47
+ type: 'merkleRootMultisigIsm',
48
+ validators: ['0xVALIDATOR1'],
49
+ threshold: 1,
50
+ },
51
+ deployed: { address: mockIsmAddress },
52
+ };
53
+ const mockDefaultHook = {
54
+ artifactState: ArtifactState.DEPLOYED,
55
+ config: {
56
+ type: 'merkleTreeHook',
57
+ },
58
+ deployed: { address: mockDefaultHookAddress },
59
+ };
60
+ const mockRequiredHook = {
61
+ artifactState: ArtifactState.DEPLOYED,
62
+ config: {
63
+ type: 'interchainGasPaymaster',
64
+ owner: mockOwner,
65
+ beneficiary: '0xBENEFICIARY',
66
+ oracleKey: '0xORACLE',
67
+ overhead: {},
68
+ oracleConfig: {},
69
+ },
70
+ deployed: { address: mockRequiredHookAddress },
71
+ };
72
+ beforeEach(async () => {
73
+ mockIsmArtifactManager = {
74
+ readIsm: sinon.stub(),
75
+ createReader: sinon.stub().returns({ read: sinon.stub() }),
76
+ createWriter: sinon.stub().returns({
77
+ create: sinon.stub(),
78
+ update: sinon.stub(),
79
+ read: sinon.stub(),
80
+ }),
81
+ };
82
+ mockHookArtifactManager = {
83
+ readHook: sinon.stub(),
84
+ createReader: sinon.stub().returns({ read: sinon.stub() }),
85
+ createWriter: sinon.stub().returns({
86
+ create: sinon.stub(),
87
+ update: sinon.stub(),
88
+ read: sinon.stub(),
89
+ }),
90
+ };
91
+ mockProtocolProvider = {
92
+ createProvider: sinon.stub(),
93
+ createSigner: sinon.stub(),
94
+ createSubmitter: sinon.stub(),
95
+ createIsmArtifactManager: sinon.stub(),
96
+ createHookArtifactManager: sinon.stub().returns(mockHookArtifactManager),
97
+ createMailboxArtifactManager: sinon.stub(),
98
+ createValidatorAnnounceArtifactManager: sinon.stub(),
99
+ getMinGas: sinon.stub(),
100
+ createWarpArtifactManager: sinon.stub(),
101
+ };
102
+ mockProtocolProvider.createIsmArtifactManager = sinon
103
+ .stub()
104
+ .returns(mockIsmArtifactManager);
105
+ signer = await MockSigner.connectWithSigner();
106
+ getSignerAddressStub = sinon.stub().returns(mockSignerAddress);
107
+ sinon.stub(signer, 'getSignerAddress').callsFake(getSignerAddressStub);
108
+ sendAndConfirmTxStub = sinon
109
+ .stub()
110
+ .resolves(mockReceipt);
111
+ sinon
112
+ .stub(signer, 'sendAndConfirmTransaction')
113
+ .callsFake(sendAndConfirmTxStub);
114
+ const mailboxCreateStub = sinon
115
+ .stub()
116
+ .resolves([
117
+ {
118
+ artifactState: ArtifactState.DEPLOYED,
119
+ config: {
120
+ owner: mockSignerAddress,
121
+ defaultIsm: {
122
+ artifactState: ArtifactState.DEPLOYED,
123
+ config: mockIsm.config,
124
+ deployed: mockIsm.deployed,
125
+ },
126
+ defaultHook: {
127
+ artifactState: ArtifactState.UNDERIVED,
128
+ deployed: { address: ZERO_ADDRESS_HEX_32 },
129
+ },
130
+ requiredHook: {
131
+ artifactState: ArtifactState.UNDERIVED,
132
+ deployed: { address: ZERO_ADDRESS_HEX_32 },
133
+ },
134
+ },
135
+ deployed: { address: mockMailboxAddress, domainId: mockDomainId },
136
+ },
137
+ [mockReceipt],
138
+ ]);
139
+ const mailboxUpdateStub = sinon
140
+ .stub()
141
+ .resolves([]);
142
+ const mockMailboxWriter = {
143
+ create: mailboxCreateStub,
144
+ update: mailboxUpdateStub,
145
+ read: sinon.stub(),
146
+ };
147
+ createMailboxWriterStub = sinon.stub().returns(mockMailboxWriter);
148
+ mailboxArtifactManager = {
149
+ readMailbox: sinon.stub(),
150
+ createReader: sinon.stub(),
151
+ createWriter: createMailboxWriterStub,
152
+ };
153
+ const vaCreateStub = sinon
154
+ .stub()
155
+ .resolves([
156
+ {
157
+ artifactState: ArtifactState.DEPLOYED,
158
+ config: { mailboxAddress: mockMailboxAddress },
159
+ deployed: { address: mockValidatorAnnounceAddress },
160
+ },
161
+ [mockReceipt],
162
+ ]);
163
+ const mockVAWriter = {
164
+ create: vaCreateStub,
165
+ update: sinon.stub(),
166
+ read: sinon.stub(),
167
+ };
168
+ createVAWriterStub = sinon.stub().returns(mockVAWriter);
169
+ validatorAnnounceArtifactManager = {
170
+ readValidatorAnnounce: sinon.stub(),
171
+ createReader: sinon.stub(),
172
+ createWriter: createVAWriterStub,
173
+ };
174
+ chainMetadata = {
175
+ name: chainName,
176
+ domainId: mockDomainId,
177
+ protocol: TestProtocol,
178
+ chainId: mockDomainId,
179
+ };
180
+ chainLookup = {
181
+ getChainMetadata: sinon
182
+ .stub()
183
+ .returns(chainMetadata),
184
+ getChainName: sinon.stub().returns(chainName),
185
+ getDomainId: sinon
186
+ .stub()
187
+ .returns(mockDomainId),
188
+ getKnownChainNames: sinon.stub().returns([chainName]),
189
+ };
190
+ coreWriter = new CoreWriter(mailboxArtifactManager, validatorAnnounceArtifactManager, chainMetadata, chainLookup, signer);
191
+ });
192
+ afterEach(() => {
193
+ sinon.restore();
194
+ });
195
+ describe('create', () => {
196
+ it('should deploy mailbox with NEW ISM and NEW hooks', async () => {
197
+ // ARRANGE
198
+ const artifact = {
199
+ artifactState: ArtifactState.NEW,
200
+ config: {
201
+ owner: mockOwner,
202
+ defaultIsm: {
203
+ artifactState: ArtifactState.NEW,
204
+ config: mockIsm.config,
205
+ },
206
+ defaultHook: {
207
+ artifactState: ArtifactState.NEW,
208
+ config: mockDefaultHook.config,
209
+ },
210
+ requiredHook: {
211
+ artifactState: ArtifactState.NEW,
212
+ config: mockRequiredHook.config,
213
+ },
214
+ },
215
+ };
216
+ const ismCreateStub = sinon
217
+ .stub()
218
+ .callsFake(async () => [mockIsm, [mockReceipt]]);
219
+ const mockIsmWriter = {
220
+ create: ismCreateStub,
221
+ update: sinon.stub(),
222
+ read: sinon.stub(),
223
+ };
224
+ Object.defineProperty(coreWriter, 'ismWriter', {
225
+ value: mockIsmWriter,
226
+ writable: true,
227
+ });
228
+ const hookCreateStub = sinon
229
+ .stub()
230
+ .onFirstCall()
231
+ .callsFake(async () => [mockDefaultHook, [mockReceipt]])
232
+ .onSecondCall()
233
+ .callsFake(async () => [mockRequiredHook, [mockReceipt]]);
234
+ const mockHookWriter = {
235
+ create: hookCreateStub,
236
+ update: sinon.stub(),
237
+ read: sinon.stub(),
238
+ };
239
+ mockHookArtifactManager.createWriter = sinon
240
+ .stub()
241
+ .returns(mockHookWriter);
242
+ // ACT
243
+ const [result, receipts] = await coreWriter.create(artifact);
244
+ // ASSERT
245
+ expect(result.mailbox.deployed.address).to.equal(mockMailboxAddress);
246
+ expect(result.mailbox.config.owner).to.equal(mockOwner);
247
+ expect(result.validatorAnnounce).to.not.be.null;
248
+ expect(result.validatorAnnounce?.deployed.address).to.equal(mockValidatorAnnounceAddress);
249
+ expect(receipts.length).to.be.greaterThan(0);
250
+ sinon.assert.calledOnce(ismCreateStub);
251
+ sinon.assert.calledTwice(hookCreateStub);
252
+ sinon.assert.calledWith(createMailboxWriterStub, 'mailbox', signer);
253
+ sinon.assert.calledWith(createVAWriterStub, 'validatorAnnounce', signer);
254
+ });
255
+ it('should use existing ISM when DEPLOYED', async () => {
256
+ // ARRANGE
257
+ const artifact = {
258
+ artifactState: ArtifactState.NEW,
259
+ config: {
260
+ owner: mockOwner,
261
+ defaultIsm: mockIsm,
262
+ defaultHook: mockDefaultHook,
263
+ requiredHook: mockRequiredHook,
264
+ },
265
+ };
266
+ const ismCreateStub = sinon.stub();
267
+ const mockIsmWriter = {
268
+ create: ismCreateStub,
269
+ update: sinon.stub(),
270
+ read: sinon.stub(),
271
+ };
272
+ Object.defineProperty(coreWriter, 'ismWriter', {
273
+ value: mockIsmWriter,
274
+ writable: true,
275
+ });
276
+ // ACT
277
+ await coreWriter.create(artifact);
278
+ // ASSERT
279
+ sinon.assert.notCalled(ismCreateStub);
280
+ });
281
+ it('should handle protocol without validator announce support', async () => {
282
+ // ARRANGE
283
+ const coreWriterNoVA = new CoreWriter(mailboxArtifactManager, null, chainMetadata, chainLookup, signer);
284
+ const artifact = {
285
+ artifactState: ArtifactState.NEW,
286
+ config: {
287
+ owner: mockOwner,
288
+ defaultIsm: mockIsm,
289
+ defaultHook: mockDefaultHook,
290
+ requiredHook: mockRequiredHook,
291
+ },
292
+ };
293
+ const mockIsmWriter = {
294
+ create: sinon.stub(),
295
+ update: sinon.stub(),
296
+ read: sinon.stub(),
297
+ };
298
+ Object.defineProperty(coreWriterNoVA, 'ismWriter', {
299
+ value: mockIsmWriter,
300
+ writable: true,
301
+ });
302
+ // ACT
303
+ const [result] = await coreWriterNoVA.create(artifact);
304
+ // ASSERT
305
+ expect(result.validatorAnnounce).to.be.null;
306
+ });
307
+ it('should create mailbox with signer as initial owner', async () => {
308
+ // ARRANGE
309
+ const artifact = {
310
+ artifactState: ArtifactState.NEW,
311
+ config: {
312
+ owner: mockOwner,
313
+ defaultIsm: mockIsm,
314
+ defaultHook: mockDefaultHook,
315
+ requiredHook: mockRequiredHook,
316
+ },
317
+ };
318
+ const mockIsmWriter = {
319
+ create: sinon.stub(),
320
+ update: sinon.stub(),
321
+ read: sinon.stub(),
322
+ };
323
+ Object.defineProperty(coreWriter, 'ismWriter', {
324
+ value: mockIsmWriter,
325
+ writable: true,
326
+ });
327
+ // ACT
328
+ await coreWriter.create(artifact);
329
+ // ASSERT
330
+ const mailboxWriter = createMailboxWriterStub.returnValues[0];
331
+ const mailboxCreateStub = mailboxWriter.create;
332
+ const initialConfig = mailboxCreateStub.firstCall.args[0].config;
333
+ expect(initialConfig.owner).to.equal(mockSignerAddress);
334
+ expect(initialConfig.owner).to.not.equal(mockOwner);
335
+ });
336
+ it('should create mailbox with zero-address hooks initially', async () => {
337
+ // ARRANGE
338
+ const artifact = {
339
+ artifactState: ArtifactState.NEW,
340
+ config: {
341
+ owner: mockOwner,
342
+ defaultIsm: mockIsm,
343
+ defaultHook: {
344
+ artifactState: ArtifactState.NEW,
345
+ config: mockDefaultHook.config,
346
+ },
347
+ requiredHook: {
348
+ artifactState: ArtifactState.NEW,
349
+ config: mockRequiredHook.config,
350
+ },
351
+ },
352
+ };
353
+ const mockIsmWriter = {
354
+ create: sinon.stub(),
355
+ update: sinon.stub(),
356
+ read: sinon.stub(),
357
+ };
358
+ Object.defineProperty(coreWriter, 'ismWriter', {
359
+ value: mockIsmWriter,
360
+ writable: true,
361
+ });
362
+ const mockHookWriter = {
363
+ create: sinon
364
+ .stub()
365
+ .onFirstCall()
366
+ .callsFake(async () => [mockDefaultHook, [mockReceipt]])
367
+ .onSecondCall()
368
+ .callsFake(async () => [mockRequiredHook, [mockReceipt]]),
369
+ update: sinon.stub(),
370
+ read: sinon.stub(),
371
+ };
372
+ mockHookArtifactManager.createWriter = sinon
373
+ .stub()
374
+ .returns(mockHookWriter);
375
+ // ACT
376
+ await coreWriter.create(artifact);
377
+ // ASSERT
378
+ const mailboxWriter = createMailboxWriterStub.returnValues[0];
379
+ const mailboxCreateStub = mailboxWriter.create;
380
+ const initialConfig = mailboxCreateStub.firstCall.args[0].config;
381
+ expect(initialConfig.defaultHook.deployed.address).to.equal(ZERO_ADDRESS_HEX_32);
382
+ expect(initialConfig.requiredHook.deployed.address).to.equal(ZERO_ADDRESS_HEX_32);
383
+ expect(initialConfig.defaultHook.artifactState).to.equal(ArtifactState.UNDERIVED);
384
+ });
385
+ it('should keep zero-address hook placeholders for non-Starknet even when hooks are already on-chain', async () => {
386
+ const artifact = {
387
+ artifactState: ArtifactState.NEW,
388
+ config: {
389
+ owner: mockOwner,
390
+ defaultIsm: mockIsm,
391
+ defaultHook: mockDefaultHook,
392
+ requiredHook: mockRequiredHook,
393
+ },
394
+ };
395
+ const mockIsmWriter = {
396
+ create: sinon.stub(),
397
+ update: sinon.stub(),
398
+ read: sinon.stub(),
399
+ };
400
+ Object.defineProperty(coreWriter, 'ismWriter', {
401
+ value: mockIsmWriter,
402
+ writable: true,
403
+ });
404
+ await coreWriter.create(artifact);
405
+ const mailboxWriter = createMailboxWriterStub.returnValues[0];
406
+ const initialConfig = mailboxWriter.create.firstCall.args[0].config;
407
+ expect(initialConfig.defaultHook.deployed.address).to.equal(ZERO_ADDRESS_HEX_32);
408
+ expect(initialConfig.requiredHook.deployed.address).to.equal(ZERO_ADDRESS_HEX_32);
409
+ });
410
+ it('should defer Starknet noop hook bootstrap to the mailbox writer', async () => {
411
+ chainMetadata = {
412
+ ...chainMetadata,
413
+ protocol: ProtocolType.Starknet,
414
+ };
415
+ coreWriter = new CoreWriter(mailboxArtifactManager, validatorAnnounceArtifactManager, chainMetadata, chainLookup, signer);
416
+ const placeholderTx = {
417
+ to: '0xhookfactory',
418
+ data: '0xnoop',
419
+ };
420
+ const createNoopHookTxStub = sinon
421
+ .stub(signer, 'getCreateNoopHookTransaction')
422
+ .resolves(placeholderTx);
423
+ const artifact = {
424
+ artifactState: ArtifactState.NEW,
425
+ config: {
426
+ owner: mockOwner,
427
+ defaultIsm: mockIsm,
428
+ defaultHook: {
429
+ artifactState: ArtifactState.NEW,
430
+ config: mockDefaultHook.config,
431
+ },
432
+ requiredHook: {
433
+ artifactState: ArtifactState.NEW,
434
+ config: mockRequiredHook.config,
435
+ },
436
+ },
437
+ };
438
+ const mockIsmWriter = {
439
+ create: sinon.stub(),
440
+ update: sinon.stub(),
441
+ read: sinon.stub(),
442
+ };
443
+ Object.defineProperty(coreWriter, 'ismWriter', {
444
+ value: mockIsmWriter,
445
+ writable: true,
446
+ });
447
+ const mockHookWriter = {
448
+ create: sinon
449
+ .stub()
450
+ .onFirstCall()
451
+ .callsFake(async () => [mockDefaultHook, [mockReceipt]])
452
+ .onSecondCall()
453
+ .callsFake(async () => [mockRequiredHook, [mockReceipt]]),
454
+ update: sinon.stub(),
455
+ read: sinon.stub(),
456
+ };
457
+ mockHookArtifactManager.createWriter = sinon
458
+ .stub()
459
+ .returns(mockHookWriter);
460
+ await coreWriter.create(artifact);
461
+ const mailboxWriter = createMailboxWriterStub.returnValues[0];
462
+ const initialConfig = mailboxWriter.create.firstCall.args[0].config;
463
+ expect(initialConfig.defaultHook.deployed.address).to.equal(ZERO_ADDRESS_HEX_32);
464
+ expect(initialConfig.requiredHook.deployed.address).to.equal(ZERO_ADDRESS_HEX_32);
465
+ sinon.assert.notCalled(createNoopHookTxStub);
466
+ sinon.assert.notCalled(sendAndConfirmTxStub);
467
+ });
468
+ it('should pass through existing hook addresses during Starknet mailbox bootstrap', async () => {
469
+ chainMetadata = {
470
+ ...chainMetadata,
471
+ protocol: ProtocolType.Starknet,
472
+ };
473
+ coreWriter = new CoreWriter(mailboxArtifactManager, validatorAnnounceArtifactManager, chainMetadata, chainLookup, signer);
474
+ const artifact = {
475
+ artifactState: ArtifactState.NEW,
476
+ config: {
477
+ owner: mockOwner,
478
+ defaultIsm: mockIsm,
479
+ defaultHook: mockDefaultHook,
480
+ requiredHook: mockRequiredHook,
481
+ },
482
+ };
483
+ const mockIsmWriter = {
484
+ create: sinon.stub(),
485
+ update: sinon.stub(),
486
+ read: sinon.stub(),
487
+ };
488
+ Object.defineProperty(coreWriter, 'ismWriter', {
489
+ value: mockIsmWriter,
490
+ writable: true,
491
+ });
492
+ await coreWriter.create(artifact);
493
+ const mailboxWriter = createMailboxWriterStub.returnValues[0];
494
+ const initialConfig = mailboxWriter.create.firstCall.args[0].config;
495
+ expect(initialConfig.defaultHook.deployed.address).to.equal(mockDefaultHookAddress);
496
+ expect(initialConfig.requiredHook.deployed.address).to.equal(mockRequiredHookAddress);
497
+ });
498
+ it('should update mailbox with hooks and owner after deployment', async () => {
499
+ // ARRANGE
500
+ const artifact = {
501
+ artifactState: ArtifactState.NEW,
502
+ config: {
503
+ owner: mockOwner,
504
+ defaultIsm: mockIsm,
505
+ defaultHook: mockDefaultHook,
506
+ requiredHook: mockRequiredHook,
507
+ },
508
+ };
509
+ const mockIsmWriter = {
510
+ create: sinon.stub(),
511
+ update: sinon.stub(),
512
+ read: sinon.stub(),
513
+ };
514
+ Object.defineProperty(coreWriter, 'ismWriter', {
515
+ value: mockIsmWriter,
516
+ writable: true,
517
+ });
518
+ // ACT
519
+ await coreWriter.create(artifact);
520
+ // ASSERT
521
+ const mailboxWriter = createMailboxWriterStub.returnValues[0];
522
+ const mailboxUpdateStub = mailboxWriter.update;
523
+ sinon.assert.calledOnce(mailboxUpdateStub);
524
+ const updatedArtifact = mailboxUpdateStub.firstCall.args[0];
525
+ expect(updatedArtifact.config.owner).to.equal(mockOwner);
526
+ expect(updatedArtifact.config.defaultHook.deployed.address).to.equal(mockDefaultHookAddress);
527
+ expect(updatedArtifact.config.requiredHook.deployed.address).to.equal(mockRequiredHookAddress);
528
+ });
529
+ it('should execute update transactions via signer', async () => {
530
+ // ARRANGE
531
+ const mockUpdateTx = {
532
+ to: mockMailboxAddress,
533
+ data: '0xUPDATE',
534
+ annotation: 'Update hooks',
535
+ };
536
+ const mailboxCreateStub = sinon.stub().resolves([
537
+ {
538
+ artifactState: ArtifactState.DEPLOYED,
539
+ config: {
540
+ owner: mockSignerAddress,
541
+ defaultIsm: {
542
+ artifactState: ArtifactState.DEPLOYED,
543
+ config: mockIsm.config,
544
+ deployed: mockIsm.deployed,
545
+ },
546
+ defaultHook: {
547
+ artifactState: ArtifactState.UNDERIVED,
548
+ deployed: { address: ZERO_ADDRESS_HEX_32 },
549
+ },
550
+ requiredHook: {
551
+ artifactState: ArtifactState.UNDERIVED,
552
+ deployed: { address: ZERO_ADDRESS_HEX_32 },
553
+ },
554
+ },
555
+ deployed: { address: mockMailboxAddress, domainId: mockDomainId },
556
+ },
557
+ [mockReceipt],
558
+ ]);
559
+ const mailboxUpdateStub = sinon.stub().resolves([mockUpdateTx]);
560
+ const mockMailboxWriter = {
561
+ create: mailboxCreateStub,
562
+ update: mailboxUpdateStub,
563
+ read: sinon.stub(),
564
+ };
565
+ mailboxArtifactManager.createWriter = sinon
566
+ .stub()
567
+ .returns(mockMailboxWriter);
568
+ const artifact = {
569
+ artifactState: ArtifactState.NEW,
570
+ config: {
571
+ owner: mockOwner,
572
+ defaultIsm: mockIsm,
573
+ defaultHook: mockDefaultHook,
574
+ requiredHook: mockRequiredHook,
575
+ },
576
+ };
577
+ const mockIsmWriter = {
578
+ create: sinon.stub(),
579
+ update: sinon.stub(),
580
+ read: sinon.stub(),
581
+ };
582
+ Object.defineProperty(coreWriter, 'ismWriter', {
583
+ value: mockIsmWriter,
584
+ writable: true,
585
+ });
586
+ // ACT
587
+ await coreWriter.create(artifact);
588
+ // ASSERT
589
+ sinon.assert.calledWith(sendAndConfirmTxStub, mockUpdateTx);
590
+ });
591
+ it('should collect receipts from all steps', async () => {
592
+ // ARRANGE
593
+ const artifact = {
594
+ artifactState: ArtifactState.NEW,
595
+ config: {
596
+ owner: mockOwner,
597
+ defaultIsm: {
598
+ artifactState: ArtifactState.NEW,
599
+ config: mockIsm.config,
600
+ },
601
+ defaultHook: mockDefaultHook,
602
+ requiredHook: mockRequiredHook,
603
+ },
604
+ };
605
+ const mockIsmWriter = {
606
+ create: sinon
607
+ .stub()
608
+ .callsFake(async () => [mockIsm, [mockReceipt, mockReceipt]]),
609
+ update: sinon.stub(),
610
+ read: sinon.stub(),
611
+ };
612
+ Object.defineProperty(coreWriter, 'ismWriter', {
613
+ value: mockIsmWriter,
614
+ writable: true,
615
+ });
616
+ // ACT
617
+ const [, receipts] = await coreWriter.create(artifact);
618
+ // ASSERT
619
+ expect(receipts.length).to.be.greaterThan(0);
620
+ expect(receipts.length).to.be.at.least(4);
621
+ });
622
+ it('should propagate ISM deployment errors', async () => {
623
+ // ARRANGE
624
+ const error = new Error('ISM deployment failed');
625
+ const artifact = {
626
+ artifactState: ArtifactState.NEW,
627
+ config: {
628
+ owner: mockOwner,
629
+ defaultIsm: {
630
+ artifactState: ArtifactState.NEW,
631
+ config: mockIsm.config,
632
+ },
633
+ defaultHook: mockDefaultHook,
634
+ requiredHook: mockRequiredHook,
635
+ },
636
+ };
637
+ const mockIsmWriter = {
638
+ create: sinon.stub().rejects(error),
639
+ update: sinon.stub(),
640
+ read: sinon.stub(),
641
+ };
642
+ Object.defineProperty(coreWriter, 'ismWriter', {
643
+ value: mockIsmWriter,
644
+ writable: true,
645
+ });
646
+ // ACT & ASSERT
647
+ await expect(coreWriter.create(artifact)).to.be.rejectedWith('ISM deployment failed');
648
+ });
649
+ it('should propagate mailbox creation errors', async () => {
650
+ // ARRANGE
651
+ const error = new Error('Mailbox creation failed');
652
+ const mockMailboxWriter = {
653
+ create: sinon.stub().rejects(error),
654
+ update: sinon.stub(),
655
+ read: sinon.stub(),
656
+ };
657
+ mailboxArtifactManager.createWriter = sinon
658
+ .stub()
659
+ .returns(mockMailboxWriter);
660
+ const artifact = {
661
+ artifactState: ArtifactState.NEW,
662
+ config: {
663
+ owner: mockOwner,
664
+ defaultIsm: mockIsm,
665
+ defaultHook: mockDefaultHook,
666
+ requiredHook: mockRequiredHook,
667
+ },
668
+ };
669
+ const mockIsmWriter = {
670
+ create: sinon.stub(),
671
+ update: sinon.stub(),
672
+ read: sinon.stub(),
673
+ };
674
+ Object.defineProperty(coreWriter, 'ismWriter', {
675
+ value: mockIsmWriter,
676
+ writable: true,
677
+ });
678
+ // ACT & ASSERT
679
+ await expect(coreWriter.create(artifact)).to.be.rejectedWith('Mailbox creation failed');
680
+ });
681
+ });
682
+ describe('update', () => {
683
+ it('should handle ISM type change by deploying new ISM', async () => {
684
+ // ARRANGE
685
+ const currentMailbox = {
686
+ artifactState: ArtifactState.DEPLOYED,
687
+ config: {
688
+ owner: mockOwner,
689
+ defaultIsm: mockIsm,
690
+ defaultHook: mockDefaultHook,
691
+ requiredHook: mockRequiredHook,
692
+ },
693
+ deployed: { address: mockMailboxAddress, domainId: mockDomainId },
694
+ };
695
+ sinon.stub(coreWriter, 'read').resolves(currentMailbox);
696
+ const newIsm = {
697
+ artifactState: ArtifactState.DEPLOYED,
698
+ config: {
699
+ type: 'messageIdMultisigIsm',
700
+ validators: ['0xVALIDATOR2'],
701
+ threshold: 1,
702
+ },
703
+ deployed: { address: mockNewIsmAddress },
704
+ };
705
+ const expectedArtifact = {
706
+ artifactState: ArtifactState.DEPLOYED,
707
+ config: {
708
+ owner: mockOwner,
709
+ defaultIsm: {
710
+ artifactState: ArtifactState.NEW,
711
+ config: newIsm.config,
712
+ },
713
+ defaultHook: mockDefaultHook,
714
+ requiredHook: mockRequiredHook,
715
+ },
716
+ deployed: { address: mockMailboxAddress, domainId: mockDomainId },
717
+ };
718
+ const ismCreateStub = sinon
719
+ .stub()
720
+ .callsFake(async () => [newIsm, [mockReceipt]]);
721
+ const mockIsmWriter = {
722
+ create: ismCreateStub,
723
+ update: sinon.stub(),
724
+ read: sinon.stub(),
725
+ };
726
+ mockIsmArtifactManager.createWriter = sinon.stub().returns(mockIsmWriter);
727
+ const mockHookWriter = {
728
+ create: sinon.stub(),
729
+ update: sinon.stub().resolves([]),
730
+ read: sinon.stub(),
731
+ };
732
+ mockHookArtifactManager.createWriter = sinon
733
+ .stub()
734
+ .returns(mockHookWriter);
735
+ // ACT
736
+ await coreWriter.update(expectedArtifact);
737
+ // ASSERT
738
+ sinon.assert.calledOnce(ismCreateStub);
739
+ const createArg = ismCreateStub.firstCall.args[0];
740
+ expect(createArg.artifactState).to.equal(ArtifactState.NEW);
741
+ expect(createArg.config.type).to.equal('messageIdMultisigIsm');
742
+ });
743
+ it('should handle UNDERIVED ISM by using address as-is', async () => {
744
+ // ARRANGE
745
+ const currentMailbox = {
746
+ artifactState: ArtifactState.DEPLOYED,
747
+ config: {
748
+ owner: mockOwner,
749
+ defaultIsm: mockIsm,
750
+ defaultHook: mockDefaultHook,
751
+ requiredHook: mockRequiredHook,
752
+ },
753
+ deployed: { address: mockMailboxAddress, domainId: mockDomainId },
754
+ };
755
+ sinon.stub(coreWriter, 'read').resolves(currentMailbox);
756
+ const expectedArtifact = {
757
+ artifactState: ArtifactState.DEPLOYED,
758
+ config: {
759
+ owner: mockOwner,
760
+ defaultIsm: {
761
+ artifactState: ArtifactState.UNDERIVED,
762
+ deployed: { address: mockIsmAddress },
763
+ },
764
+ defaultHook: mockDefaultHook,
765
+ requiredHook: mockRequiredHook,
766
+ },
767
+ deployed: { address: mockMailboxAddress, domainId: mockDomainId },
768
+ };
769
+ const ismCreateStub = sinon.stub();
770
+ const ismUpdateStub = sinon.stub();
771
+ const mockIsmWriter = {
772
+ create: ismCreateStub,
773
+ update: ismUpdateStub,
774
+ read: sinon.stub(),
775
+ };
776
+ Object.defineProperty(coreWriter, 'ismWriter', {
777
+ value: mockIsmWriter,
778
+ writable: true,
779
+ });
780
+ const mockHookWriter = {
781
+ create: sinon.stub(),
782
+ update: sinon.stub().resolves([]),
783
+ read: sinon.stub(),
784
+ };
785
+ mockHookArtifactManager.createWriter = sinon
786
+ .stub()
787
+ .returns(mockHookWriter);
788
+ // ACT
789
+ await coreWriter.update(expectedArtifact);
790
+ // ASSERT
791
+ sinon.assert.notCalled(ismCreateStub);
792
+ sinon.assert.notCalled(ismUpdateStub);
793
+ });
794
+ it('should return empty array when no updates needed', async () => {
795
+ // ARRANGE
796
+ const currentMailbox = {
797
+ artifactState: ArtifactState.DEPLOYED,
798
+ config: {
799
+ owner: mockOwner,
800
+ defaultIsm: mockIsm,
801
+ defaultHook: mockDefaultHook,
802
+ requiredHook: mockRequiredHook,
803
+ },
804
+ deployed: { address: mockMailboxAddress, domainId: mockDomainId },
805
+ };
806
+ sinon.stub(coreWriter, 'read').resolves(currentMailbox);
807
+ const expectedArtifact = {
808
+ artifactState: ArtifactState.DEPLOYED,
809
+ config: currentMailbox.config,
810
+ deployed: { address: mockMailboxAddress, domainId: mockDomainId },
811
+ };
812
+ const mockIsmWriter = {
813
+ create: sinon.stub(),
814
+ update: sinon.stub().resolves([]),
815
+ read: sinon.stub(),
816
+ };
817
+ Object.defineProperty(coreWriter, 'ismWriter', {
818
+ value: mockIsmWriter,
819
+ writable: true,
820
+ });
821
+ const mockHookWriter = {
822
+ create: sinon.stub(),
823
+ update: sinon.stub().resolves([]),
824
+ read: sinon.stub(),
825
+ };
826
+ mockHookArtifactManager.createWriter = sinon
827
+ .stub()
828
+ .returns(mockHookWriter);
829
+ // ACT
830
+ const result = await coreWriter.update(expectedArtifact);
831
+ // ASSERT
832
+ expect(result).to.be.an('array').with.lengthOf(0);
833
+ });
834
+ it('should deploy NEW ISM when current is zero-address UNDERIVED', async () => {
835
+ // ARRANGE
836
+ const currentMailbox = {
837
+ artifactState: ArtifactState.DEPLOYED,
838
+ config: {
839
+ owner: mockOwner,
840
+ defaultIsm: {
841
+ artifactState: ArtifactState.UNDERIVED,
842
+ deployed: { address: ZERO_ADDRESS_HEX_32 },
843
+ },
844
+ defaultHook: mockDefaultHook,
845
+ requiredHook: mockRequiredHook,
846
+ },
847
+ deployed: { address: mockMailboxAddress, domainId: mockDomainId },
848
+ };
849
+ sinon.stub(coreWriter, 'read').resolves(currentMailbox);
850
+ const newIsm = {
851
+ artifactState: ArtifactState.DEPLOYED,
852
+ config: {
853
+ type: 'merkleRootMultisigIsm',
854
+ validators: ['0xVALIDATOR1'],
855
+ threshold: 1,
856
+ },
857
+ deployed: { address: mockNewIsmAddress },
858
+ };
859
+ const expectedArtifact = {
860
+ artifactState: ArtifactState.DEPLOYED,
861
+ config: {
862
+ owner: mockOwner,
863
+ defaultIsm: {
864
+ artifactState: ArtifactState.NEW,
865
+ config: newIsm.config,
866
+ },
867
+ defaultHook: mockDefaultHook,
868
+ requiredHook: mockRequiredHook,
869
+ },
870
+ deployed: { address: mockMailboxAddress, domainId: mockDomainId },
871
+ };
872
+ const ismCreateStub = sinon
873
+ .stub()
874
+ .callsFake(async () => [newIsm, [mockReceipt]]);
875
+ const mockIsmWriter = {
876
+ create: ismCreateStub,
877
+ update: sinon.stub(),
878
+ read: sinon.stub(),
879
+ };
880
+ Object.defineProperty(coreWriter, 'ismWriter', {
881
+ value: mockIsmWriter,
882
+ writable: true,
883
+ });
884
+ const mockHookWriter = {
885
+ create: sinon.stub(),
886
+ update: sinon.stub().resolves([]),
887
+ read: sinon.stub(),
888
+ };
889
+ mockHookArtifactManager.createWriter = sinon
890
+ .stub()
891
+ .returns(mockHookWriter);
892
+ // ACT
893
+ const result = await coreWriter.update(expectedArtifact);
894
+ // ASSERT
895
+ sinon.assert.calledOnce(ismCreateStub);
896
+ expect(result).to.be.an('array');
897
+ });
898
+ it('should assert artifacts are expanded before updating', async () => {
899
+ // ARRANGE
900
+ const currentMailbox = {
901
+ artifactState: ArtifactState.DEPLOYED,
902
+ config: {
903
+ owner: mockOwner,
904
+ defaultIsm: {
905
+ artifactState: ArtifactState.UNDERIVED,
906
+ deployed: { address: mockIsmAddress },
907
+ },
908
+ defaultHook: mockDefaultHook,
909
+ requiredHook: mockRequiredHook,
910
+ },
911
+ deployed: { address: mockMailboxAddress, domainId: mockDomainId },
912
+ };
913
+ sinon.stub(coreWriter, 'read').resolves(currentMailbox);
914
+ const expectedArtifact = {
915
+ artifactState: ArtifactState.DEPLOYED,
916
+ config: {
917
+ owner: mockOwner,
918
+ defaultIsm: mockIsm,
919
+ defaultHook: mockDefaultHook,
920
+ requiredHook: mockRequiredHook,
921
+ },
922
+ deployed: { address: mockMailboxAddress, domainId: mockDomainId },
923
+ };
924
+ // ACT & ASSERT
925
+ await expect(coreWriter.update(expectedArtifact)).to.be.rejectedWith('Expected defaultIsm to be DEPLOYED or UNDERIVED with zero address');
926
+ });
927
+ it('should deploy NEW hook during update', async () => {
928
+ // ARRANGE
929
+ const currentMailbox = {
930
+ artifactState: ArtifactState.DEPLOYED,
931
+ config: {
932
+ owner: mockOwner,
933
+ defaultIsm: mockIsm,
934
+ defaultHook: {
935
+ artifactState: ArtifactState.UNDERIVED,
936
+ deployed: { address: ZERO_ADDRESS_HEX_32 },
937
+ },
938
+ requiredHook: mockRequiredHook,
939
+ },
940
+ deployed: { address: mockMailboxAddress, domainId: mockDomainId },
941
+ };
942
+ sinon.stub(coreWriter, 'read').resolves(currentMailbox);
943
+ const newDefaultHook = {
944
+ artifactState: ArtifactState.DEPLOYED,
945
+ config: { type: 'merkleTreeHook' },
946
+ deployed: { address: mockDefaultHookAddress },
947
+ };
948
+ const expectedArtifact = {
949
+ artifactState: ArtifactState.DEPLOYED,
950
+ config: {
951
+ owner: mockOwner,
952
+ defaultIsm: mockIsm,
953
+ defaultHook: {
954
+ artifactState: ArtifactState.NEW,
955
+ config: newDefaultHook.config,
956
+ },
957
+ requiredHook: mockRequiredHook,
958
+ },
959
+ deployed: { address: mockMailboxAddress, domainId: mockDomainId },
960
+ };
961
+ const mockIsmWriter = {
962
+ create: sinon.stub(),
963
+ update: sinon.stub().resolves([]),
964
+ read: sinon.stub(),
965
+ };
966
+ Object.defineProperty(coreWriter, 'ismWriter', {
967
+ value: mockIsmWriter,
968
+ writable: true,
969
+ });
970
+ const hookCreateStub = sinon
971
+ .stub()
972
+ .callsFake(async () => [newDefaultHook, [mockReceipt]]);
973
+ const mockHookWriter = {
974
+ create: hookCreateStub,
975
+ update: sinon.stub().resolves([]),
976
+ read: sinon.stub(),
977
+ };
978
+ mockHookArtifactManager.createWriter = sinon
979
+ .stub()
980
+ .returns(mockHookWriter);
981
+ // ACT
982
+ await coreWriter.update(expectedArtifact);
983
+ // ASSERT
984
+ sinon.assert.calledOnce(hookCreateStub);
985
+ });
986
+ it('should handle owner change', async () => {
987
+ // ARRANGE
988
+ const newOwner = '0xNEWOWNER';
989
+ const currentMailbox = {
990
+ artifactState: ArtifactState.DEPLOYED,
991
+ config: {
992
+ owner: mockOwner,
993
+ defaultIsm: mockIsm,
994
+ defaultHook: mockDefaultHook,
995
+ requiredHook: mockRequiredHook,
996
+ },
997
+ deployed: { address: mockMailboxAddress, domainId: mockDomainId },
998
+ };
999
+ sinon.stub(coreWriter, 'read').resolves(currentMailbox);
1000
+ const expectedArtifact = {
1001
+ artifactState: ArtifactState.DEPLOYED,
1002
+ config: {
1003
+ owner: newOwner,
1004
+ defaultIsm: mockIsm,
1005
+ defaultHook: mockDefaultHook,
1006
+ requiredHook: mockRequiredHook,
1007
+ },
1008
+ deployed: { address: mockMailboxAddress, domainId: mockDomainId },
1009
+ };
1010
+ const mockIsmWriter = {
1011
+ create: sinon.stub(),
1012
+ update: sinon.stub().resolves([]),
1013
+ read: sinon.stub(),
1014
+ };
1015
+ Object.defineProperty(coreWriter, 'ismWriter', {
1016
+ value: mockIsmWriter,
1017
+ writable: true,
1018
+ });
1019
+ const mockHookWriter = {
1020
+ create: sinon.stub(),
1021
+ update: sinon.stub().resolves([]),
1022
+ read: sinon.stub(),
1023
+ };
1024
+ mockHookArtifactManager.createWriter = sinon
1025
+ .stub()
1026
+ .returns(mockHookWriter);
1027
+ // ACT
1028
+ await coreWriter.update(expectedArtifact);
1029
+ // ASSERT
1030
+ const mailboxWriter = createMailboxWriterStub.returnValues[0];
1031
+ const updatedArtifact = mailboxWriter.update.firstCall.args[0];
1032
+ expect(updatedArtifact.config.owner).to.equal(newOwner);
1033
+ });
1034
+ it('should wire correct addresses into mailbox update', async () => {
1035
+ // ARRANGE
1036
+ const newIsm = {
1037
+ artifactState: ArtifactState.DEPLOYED,
1038
+ config: {
1039
+ type: 'messageIdMultisigIsm',
1040
+ validators: ['0xVALIDATOR2'],
1041
+ threshold: 1,
1042
+ },
1043
+ deployed: { address: mockNewIsmAddress },
1044
+ };
1045
+ const currentMailbox = {
1046
+ artifactState: ArtifactState.DEPLOYED,
1047
+ config: {
1048
+ owner: mockOwner,
1049
+ defaultIsm: mockIsm,
1050
+ defaultHook: mockDefaultHook,
1051
+ requiredHook: mockRequiredHook,
1052
+ },
1053
+ deployed: { address: mockMailboxAddress, domainId: mockDomainId },
1054
+ };
1055
+ sinon.stub(coreWriter, 'read').resolves(currentMailbox);
1056
+ const expectedArtifact = {
1057
+ artifactState: ArtifactState.DEPLOYED,
1058
+ config: {
1059
+ owner: mockOwner,
1060
+ defaultIsm: {
1061
+ artifactState: ArtifactState.NEW,
1062
+ config: newIsm.config,
1063
+ },
1064
+ defaultHook: mockDefaultHook,
1065
+ requiredHook: mockRequiredHook,
1066
+ },
1067
+ deployed: { address: mockMailboxAddress, domainId: mockDomainId },
1068
+ };
1069
+ const ismCreateStub = sinon
1070
+ .stub()
1071
+ .callsFake(async () => [newIsm, [mockReceipt]]);
1072
+ const mockIsmWriter = {
1073
+ create: ismCreateStub,
1074
+ update: sinon.stub(),
1075
+ read: sinon.stub(),
1076
+ };
1077
+ mockIsmArtifactManager.createWriter = sinon.stub().returns(mockIsmWriter);
1078
+ const mockHookWriter = {
1079
+ create: sinon.stub(),
1080
+ update: sinon.stub().resolves([]),
1081
+ read: sinon.stub(),
1082
+ };
1083
+ mockHookArtifactManager.createWriter = sinon
1084
+ .stub()
1085
+ .returns(mockHookWriter);
1086
+ // ACT
1087
+ await coreWriter.update(expectedArtifact);
1088
+ // ASSERT
1089
+ const mailboxWriter = createMailboxWriterStub.returnValues[0];
1090
+ const updatedArtifact = mailboxWriter.update.firstCall.args[0];
1091
+ expect(updatedArtifact.config.defaultIsm.deployed.address).to.equal(mockNewIsmAddress);
1092
+ expect(updatedArtifact.config.defaultHook.deployed.address).to.equal(mockDefaultHookAddress);
1093
+ expect(updatedArtifact.config.requiredHook.deployed.address).to.equal(mockRequiredHookAddress);
1094
+ });
1095
+ });
1096
+ });
1097
+ //# sourceMappingURL=core-writer.test.js.map