@0xsequence/catapult 1.3.7 → 1.3.9
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.
- package/README.md +1 -0
- package/dist/lib/__tests__/deployer.spec.js +309 -0
- package/dist/lib/__tests__/deployer.spec.js.map +1 -1
- package/dist/lib/core/engine.d.ts +3 -2
- package/dist/lib/core/engine.d.ts.map +1 -1
- package/dist/lib/core/engine.js.map +1 -1
- package/dist/lib/deployer.d.ts.map +1 -1
- package/dist/lib/deployer.js +33 -5
- package/dist/lib/deployer.js.map +1 -1
- package/dist/lib/std/templates/arachnid-deterministic-deployment-proxy.yaml +68 -0
- package/package.json +1 -1
- package/src/lib/__tests__/deployer.spec.ts +414 -0
- package/src/lib/core/engine.ts +1 -1
- package/src/lib/deployer.ts +94 -63
- package/src/lib/std/templates/arachnid-deterministic-deployment-proxy.yaml +68 -0
package/src/lib/deployer.ts
CHANGED
|
@@ -16,31 +16,31 @@ import type { RunSummaryEvent } from './events'
|
|
|
16
16
|
export interface DeployerOptions {
|
|
17
17
|
/** The root directory of the deployment project. */
|
|
18
18
|
projectRoot: string
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
/** The private key of the EOA to be used as the signer/relayer. Optional if an implicit sender from RPC is desired. */
|
|
21
21
|
privateKey?: string
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
/** An array of network configurations to use for deployment. */
|
|
24
24
|
networks: Network[]
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
/** Optional: An array of job names to execute. If not provided, all jobs are considered. */
|
|
27
27
|
runJobs?: string[]
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
/** Optional: An array of chain IDs to run on. If not provided, all configured networks are used. */
|
|
30
30
|
runOnNetworks?: number[]
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
/** Optional: Custom event emitter instance. If not provided, uses the global singleton. */
|
|
33
33
|
eventEmitter?: DeploymentEventEmitter
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
/** Optional: Project loader options (e.g., whether to load standard templates). */
|
|
36
36
|
loaderOptions?: ProjectLoaderOptions
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
/** Optional Etherscan API key for contract verification. */
|
|
39
39
|
etherscanApiKey?: string
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
/** Optional: Stop execution as soon as any job fails. Defaults to false. */
|
|
42
42
|
failEarly?: boolean
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
/** Optional: Skip post-execution check of skip conditions. Defaults to false (post-check enabled). */
|
|
45
45
|
noPostCheckConditions?: boolean
|
|
46
46
|
|
|
@@ -68,11 +68,11 @@ export class Deployer {
|
|
|
68
68
|
private readonly loader: ProjectLoader
|
|
69
69
|
private readonly noPostCheckConditions: boolean
|
|
70
70
|
private readonly showSummary: boolean
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
// Store both successful and failed execution results
|
|
73
73
|
private readonly results = new Map<string, {
|
|
74
74
|
job: Job;
|
|
75
|
-
outputs: Map<number, { status: 'success' | 'error'; data: Map<string, unknown> | string }>
|
|
75
|
+
outputs: Map<number, { status: 'success' | 'error' | 'skipped'; data: Map<string, unknown> | string }>
|
|
76
76
|
}>()
|
|
77
77
|
private graph?: DependencyGraph
|
|
78
78
|
|
|
@@ -97,7 +97,7 @@ export class Deployer {
|
|
|
97
97
|
projectRoot: this.options.projectRoot
|
|
98
98
|
}
|
|
99
99
|
})
|
|
100
|
-
|
|
100
|
+
|
|
101
101
|
try {
|
|
102
102
|
// 1. Load all project artifacts, templates, and jobs.
|
|
103
103
|
this.events.emitEvent({
|
|
@@ -107,9 +107,9 @@ export class Deployer {
|
|
|
107
107
|
projectRoot: this.options.projectRoot
|
|
108
108
|
}
|
|
109
109
|
})
|
|
110
|
-
|
|
110
|
+
|
|
111
111
|
await this.loader.load()
|
|
112
|
-
|
|
112
|
+
|
|
113
113
|
this.events.emitEvent({
|
|
114
114
|
type: 'project_loaded',
|
|
115
115
|
level: 'info',
|
|
@@ -118,7 +118,7 @@ export class Deployer {
|
|
|
118
118
|
templateCount: this.loader.templates.size
|
|
119
119
|
}
|
|
120
120
|
})
|
|
121
|
-
|
|
121
|
+
|
|
122
122
|
// 2. Build the dependency graph and determine execution order.
|
|
123
123
|
const graph = new DependencyGraph(this.loader.jobs, this.loader.templates)
|
|
124
124
|
this.graph = graph
|
|
@@ -142,7 +142,7 @@ export class Deployer {
|
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
144
|
const targetNetworks = this.getTargetNetworks()
|
|
145
|
-
|
|
145
|
+
|
|
146
146
|
this.events.emitEvent({
|
|
147
147
|
type: 'execution_plan',
|
|
148
148
|
level: 'info',
|
|
@@ -163,12 +163,12 @@ export class Deployer {
|
|
|
163
163
|
noPostCheckConditions: this.noPostCheckConditions,
|
|
164
164
|
ignoreVerifyErrors: this.options.ignoreVerifyErrors ?? false
|
|
165
165
|
})
|
|
166
|
-
|
|
166
|
+
|
|
167
167
|
// Track if any jobs have failed
|
|
168
168
|
let hasFailures = false
|
|
169
169
|
// Emit signer info once per network (chainId)
|
|
170
170
|
const signerInfoPrintedForChain = new Set<number>()
|
|
171
|
-
|
|
171
|
+
|
|
172
172
|
for (const network of targetNetworks) {
|
|
173
173
|
this.events.emitEvent({
|
|
174
174
|
type: 'network_started',
|
|
@@ -180,7 +180,12 @@ export class Deployer {
|
|
|
180
180
|
})
|
|
181
181
|
for (const jobName of jobsToRun) {
|
|
182
182
|
const job = this.loader.jobs.get(jobName)!
|
|
183
|
-
|
|
183
|
+
|
|
184
|
+
// Initialize results storage for this job if not exists
|
|
185
|
+
if (!this.results.has(job.name)) {
|
|
186
|
+
this.results.set(job.name, { job, outputs: new Map() })
|
|
187
|
+
}
|
|
188
|
+
|
|
184
189
|
if (this.shouldSkipJobOnNetwork(job, network)) {
|
|
185
190
|
this.events.emitEvent({
|
|
186
191
|
type: 'job_skipped',
|
|
@@ -191,14 +196,16 @@ export class Deployer {
|
|
|
191
196
|
reason: 'configuration'
|
|
192
197
|
}
|
|
193
198
|
})
|
|
199
|
+
|
|
200
|
+
// Store skipped result
|
|
201
|
+
this.results.get(job.name)!.outputs.set(network.chainId, {
|
|
202
|
+
status: 'skipped',
|
|
203
|
+
data: 'Job skipped due to network configuration'
|
|
204
|
+
})
|
|
205
|
+
|
|
194
206
|
continue
|
|
195
207
|
}
|
|
196
|
-
|
|
197
|
-
// Initialize results storage for this job if not exists
|
|
198
|
-
if (!this.results.has(job.name)) {
|
|
199
|
-
this.results.set(job.name, { job, outputs: new Map() })
|
|
200
|
-
}
|
|
201
|
-
|
|
208
|
+
|
|
202
209
|
let context: ExecutionContext | undefined
|
|
203
210
|
try {
|
|
204
211
|
context = new ExecutionContext(
|
|
@@ -212,7 +219,7 @@ export class Deployer {
|
|
|
212
219
|
if (typeof (context as unknown as { setJobConstants?: (constants: unknown) => void }).setJobConstants === 'function') {
|
|
213
220
|
(context as unknown as { setJobConstants: (constants: unknown) => void }).setJobConstants(job.constants)
|
|
214
221
|
}
|
|
215
|
-
|
|
222
|
+
|
|
216
223
|
// Emit signer info once per network using the first job's context
|
|
217
224
|
if (!signerInfoPrintedForChain.has(network.chainId)) {
|
|
218
225
|
try {
|
|
@@ -253,11 +260,35 @@ export class Deployer {
|
|
|
253
260
|
}
|
|
254
261
|
}
|
|
255
262
|
|
|
263
|
+
// Check job-level skip conditions before execution
|
|
264
|
+
if (job.skip_condition) {
|
|
265
|
+
const shouldSkip = await engine.evaluateSkipConditions(job.skip_condition, context, new Map())
|
|
266
|
+
if (shouldSkip) {
|
|
267
|
+
// Store skipped result
|
|
268
|
+
this.results.get(job.name)!.outputs.set(network.chainId, {
|
|
269
|
+
status: 'skipped',
|
|
270
|
+
data: `Job "${job.name}" skipped due to skip condition`
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
this.events.emitEvent({
|
|
274
|
+
type: 'job_skipped',
|
|
275
|
+
level: 'warn',
|
|
276
|
+
data: {
|
|
277
|
+
jobName: job.name,
|
|
278
|
+
networkName: network.name,
|
|
279
|
+
reason: 'skip_condition'
|
|
280
|
+
}
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
continue // Skip to next job
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
256
287
|
// Populate context with outputs from previously executed dependent jobs
|
|
257
288
|
this.populateContextWithDependentJobOutputs(job, context, network)
|
|
258
|
-
|
|
289
|
+
|
|
259
290
|
await engine.executeJob(job, context)
|
|
260
|
-
|
|
291
|
+
|
|
261
292
|
// Store successful results
|
|
262
293
|
this.results.get(job.name)!.outputs.set(network.chainId, {
|
|
263
294
|
status: 'success',
|
|
@@ -270,7 +301,7 @@ export class Deployer {
|
|
|
270
301
|
status: 'error',
|
|
271
302
|
data: errorMessage
|
|
272
303
|
})
|
|
273
|
-
|
|
304
|
+
|
|
274
305
|
this.events.emitEvent({
|
|
275
306
|
type: 'job_execution_failed',
|
|
276
307
|
level: 'error',
|
|
@@ -281,15 +312,15 @@ export class Deployer {
|
|
|
281
312
|
error: errorMessage
|
|
282
313
|
}
|
|
283
314
|
})
|
|
284
|
-
|
|
315
|
+
|
|
285
316
|
// Mark that we have failures
|
|
286
317
|
hasFailures = true
|
|
287
|
-
|
|
318
|
+
|
|
288
319
|
// If fail-early is enabled, throw the error immediately
|
|
289
320
|
if (this.options.failEarly) {
|
|
290
321
|
throw error
|
|
291
322
|
}
|
|
292
|
-
|
|
323
|
+
|
|
293
324
|
// Otherwise, continue to next job/network
|
|
294
325
|
} finally {
|
|
295
326
|
// Clean up the context to prevent hanging connections
|
|
@@ -312,7 +343,7 @@ export class Deployer {
|
|
|
312
343
|
}
|
|
313
344
|
}
|
|
314
345
|
}
|
|
315
|
-
|
|
346
|
+
|
|
316
347
|
// 5. Write results to output files.
|
|
317
348
|
await this.writeOutputFiles()
|
|
318
349
|
|
|
@@ -386,18 +417,13 @@ export class Deployer {
|
|
|
386
417
|
const jobCount = this.results.size
|
|
387
418
|
let successCount = 0
|
|
388
419
|
let failedCount = 0
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
// Detect skipped by comparing planned jobs across networks vs executed entries
|
|
392
|
-
// Here we approximate: an entry exists per job and per network outcome. We count
|
|
393
|
-
// successes/errors; skips were emitted as events during execution and are not persisted
|
|
394
|
-
// in results. We cannot perfectly reconstruct skipped count without tracking, so we
|
|
395
|
-
// expose it as 0 for now; could be improved by tracking per-network skip events.
|
|
420
|
+
let skippedCount = 0
|
|
396
421
|
|
|
397
422
|
for (const [, result] of this.results) {
|
|
398
423
|
for (const [, netResult] of result.outputs) {
|
|
399
424
|
if (netResult.status === 'success') successCount++
|
|
400
|
-
else
|
|
425
|
+
else if (netResult.status === 'skipped') skippedCount++
|
|
426
|
+
else if (netResult.status === 'error') failedCount++
|
|
401
427
|
}
|
|
402
428
|
}
|
|
403
429
|
|
|
@@ -437,7 +463,7 @@ export class Deployer {
|
|
|
437
463
|
*/
|
|
438
464
|
private emitVerificationWarningsReport(engine: ExecutionEngine): void {
|
|
439
465
|
const warnings = engine.getVerificationWarnings()
|
|
440
|
-
|
|
466
|
+
|
|
441
467
|
if (warnings.length > 0) {
|
|
442
468
|
this.events.emitEvent({
|
|
443
469
|
type: 'verification_warnings_report',
|
|
@@ -530,7 +556,7 @@ export class Deployer {
|
|
|
530
556
|
const allowed = new Set<string>([...nonDeprecatedJobs, ...requiredDeprecated])
|
|
531
557
|
return fullOrder.filter(name => allowed.has(name))
|
|
532
558
|
}
|
|
533
|
-
|
|
559
|
+
|
|
534
560
|
// Expand patterns to concrete names
|
|
535
561
|
const expandedRunJobs = expandRunJobs(this.options.runJobs)
|
|
536
562
|
const explicitlyRequested = new Set<string>(expandedRunJobs)
|
|
@@ -557,7 +583,7 @@ export class Deployer {
|
|
|
557
583
|
return this.options.runDeprecated === true
|
|
558
584
|
})
|
|
559
585
|
const allowedSet = new Set(filtered)
|
|
560
|
-
|
|
586
|
+
|
|
561
587
|
// Filter the original execution order to only include the required jobs, preserving the correct sequence.
|
|
562
588
|
return fullOrder.filter(jobName => allowedSet.has(jobName))
|
|
563
589
|
}
|
|
@@ -569,10 +595,10 @@ export class Deployer {
|
|
|
569
595
|
if (!this.options.runOnNetworks || this.options.runOnNetworks.length === 0) {
|
|
570
596
|
return this.options.networks // Run on all configured networks
|
|
571
597
|
}
|
|
572
|
-
|
|
598
|
+
|
|
573
599
|
const targetChainIds = new Set(this.options.runOnNetworks)
|
|
574
600
|
const filteredNetworks = this.options.networks.filter(n => targetChainIds.has(n.chainId))
|
|
575
|
-
|
|
601
|
+
|
|
576
602
|
if (filteredNetworks.length !== this.options.runOnNetworks.length) {
|
|
577
603
|
const foundIds = new Set(filteredNetworks.map(n => n.chainId))
|
|
578
604
|
const missingIds = this.options.runOnNetworks.filter(id => !foundIds.has(id))
|
|
@@ -584,7 +610,7 @@ export class Deployer {
|
|
|
584
610
|
}
|
|
585
611
|
})
|
|
586
612
|
}
|
|
587
|
-
|
|
613
|
+
|
|
588
614
|
return filteredNetworks
|
|
589
615
|
}
|
|
590
616
|
|
|
@@ -611,7 +637,7 @@ export class Deployer {
|
|
|
611
637
|
}
|
|
612
638
|
}
|
|
613
639
|
}
|
|
614
|
-
|
|
640
|
+
|
|
615
641
|
// Check minimal EVM hardfork requirement if present on job and network declares an EVM version
|
|
616
642
|
if (jobWithNetworkFilters.min_evm_version) {
|
|
617
643
|
const jobMin = this.normalizeEvmVersion(jobWithNetworkFilters.min_evm_version)
|
|
@@ -622,7 +648,7 @@ export class Deployer {
|
|
|
622
648
|
}
|
|
623
649
|
// If network has no evmVersion declared, do not skip (assume compatible)
|
|
624
650
|
}
|
|
625
|
-
|
|
651
|
+
|
|
626
652
|
return false // Run by default
|
|
627
653
|
}
|
|
628
654
|
|
|
@@ -704,6 +730,11 @@ export class Deployer {
|
|
|
704
730
|
throw new Error(`Job "${job.name}" depends on "${dependentJobName}", but "${dependentJobName}" has not been executed on network ${network.name} (chainId: ${network.chainId}).`)
|
|
705
731
|
}
|
|
706
732
|
|
|
733
|
+
// Skip jobs don't provide outputs, but they don't prevent dependent jobs from running
|
|
734
|
+
if (networkResult.status === 'skipped') {
|
|
735
|
+
continue
|
|
736
|
+
}
|
|
737
|
+
|
|
707
738
|
if (networkResult.status !== 'success') {
|
|
708
739
|
const errorMessage = typeof networkResult.data === 'string' ? networkResult.data : 'Unknown error'
|
|
709
740
|
throw new Error(`Job "${job.name}" depends on "${dependentJobName}", but "${dependentJobName}" failed: ${errorMessage}`)
|
|
@@ -736,7 +767,7 @@ export class Deployer {
|
|
|
736
767
|
|
|
737
768
|
const outputRoot = path.join(this.options.projectRoot, 'output')
|
|
738
769
|
await fs.mkdir(outputRoot, { recursive: true })
|
|
739
|
-
|
|
770
|
+
|
|
740
771
|
this.events.emitEvent({
|
|
741
772
|
type: 'output_writing_started',
|
|
742
773
|
level: 'info'
|
|
@@ -765,7 +796,7 @@ export class Deployer {
|
|
|
765
796
|
const outputFilePath = path.join(outputRoot, relativeJobSubpath)
|
|
766
797
|
const outputFileDir = path.dirname(outputFilePath)
|
|
767
798
|
await fs.mkdir(outputFileDir, { recursive: true })
|
|
768
|
-
|
|
799
|
+
|
|
769
800
|
// Group networks by identical status and outputs
|
|
770
801
|
const groupedResults = this.groupNetworkResults(resultData.outputs, resultData.job)
|
|
771
802
|
|
|
@@ -775,7 +806,7 @@ export class Deployer {
|
|
|
775
806
|
lastRun: new Date().toISOString(),
|
|
776
807
|
networks: groupedResults
|
|
777
808
|
}
|
|
778
|
-
|
|
809
|
+
|
|
779
810
|
await fs.writeFile(outputFilePath, JSON.stringify(fileContent, null, 2))
|
|
780
811
|
this.events.emitEvent({
|
|
781
812
|
type: 'output_file_written',
|
|
@@ -875,20 +906,20 @@ export class Deployer {
|
|
|
875
906
|
*/
|
|
876
907
|
private filterOutDependencyOutputs(outputs: Map<string, unknown>, job: Job): Record<string, unknown> {
|
|
877
908
|
const filtered = new Map<string, unknown>()
|
|
878
|
-
|
|
909
|
+
|
|
879
910
|
// Get list of dependency job names
|
|
880
911
|
const dependencyNames = job.depends_on || []
|
|
881
|
-
|
|
912
|
+
|
|
882
913
|
for (const [key, value] of outputs) {
|
|
883
914
|
// Check if this output key starts with any dependency job name prefix
|
|
884
915
|
const isDependencyOutput = dependencyNames.some(depName => key.startsWith(`${depName}.`))
|
|
885
|
-
|
|
916
|
+
|
|
886
917
|
// Only include outputs that are NOT from dependencies
|
|
887
918
|
if (!isDependencyOutput) {
|
|
888
919
|
filtered.set(key, value)
|
|
889
920
|
}
|
|
890
921
|
}
|
|
891
|
-
|
|
922
|
+
|
|
892
923
|
return Object.fromEntries(filtered)
|
|
893
924
|
}
|
|
894
925
|
|
|
@@ -897,8 +928,8 @@ export class Deployer {
|
|
|
897
928
|
* - Success states with identical outputs are grouped together with chainIds array
|
|
898
929
|
* - Error states are kept separate (one entry per network)
|
|
899
930
|
*/
|
|
900
|
-
private groupNetworkResults(outputs: Map<number, { status: 'success' | 'error'; data: Map<string, unknown> | string }>, job: Job): Array<{
|
|
901
|
-
status: 'success' | 'error';
|
|
931
|
+
private groupNetworkResults(outputs: Map<number, { status: 'success' | 'error' | 'skipped'; data: Map<string, unknown> | string }>, job: Job): Array<{
|
|
932
|
+
status: 'success' | 'error' | 'skipped';
|
|
902
933
|
chainIds?: string[];
|
|
903
934
|
chainId?: string;
|
|
904
935
|
outputs?: Record<string, unknown>;
|
|
@@ -910,20 +941,20 @@ export class Deployer {
|
|
|
910
941
|
chainId: string;
|
|
911
942
|
error: string;
|
|
912
943
|
}> = []
|
|
913
|
-
|
|
944
|
+
|
|
914
945
|
for (const [chainId, result] of outputs.entries()) {
|
|
915
946
|
if (result.status === 'success') {
|
|
916
947
|
// Group successful results by identical outputs, filtered by action output flags
|
|
917
948
|
const outputsObj = result.data instanceof Map ? this.filterOutputsByActionFlags(result.data, job) : {}
|
|
918
949
|
const key = JSON.stringify(outputsObj)
|
|
919
|
-
|
|
950
|
+
|
|
920
951
|
if (!successGroups.has(key)) {
|
|
921
952
|
successGroups.set(key, {
|
|
922
953
|
chainIds: [],
|
|
923
954
|
outputs: outputsObj
|
|
924
955
|
})
|
|
925
956
|
}
|
|
926
|
-
|
|
957
|
+
|
|
927
958
|
successGroups.get(key)!.chainIds.push(chainId.toString())
|
|
928
959
|
} else {
|
|
929
960
|
// Keep error results separate - one entry per network
|
|
@@ -934,14 +965,14 @@ export class Deployer {
|
|
|
934
965
|
})
|
|
935
966
|
}
|
|
936
967
|
}
|
|
937
|
-
|
|
968
|
+
|
|
938
969
|
// Convert success groups to array format
|
|
939
970
|
const successEntries = Array.from(successGroups.values()).map(group => ({
|
|
940
971
|
status: 'success' as const,
|
|
941
972
|
chainIds: group.chainIds.sort(), // Sort for consistent output
|
|
942
973
|
outputs: group.outputs
|
|
943
974
|
}))
|
|
944
|
-
|
|
975
|
+
|
|
945
976
|
// Return all entries: successes first, then errors
|
|
946
977
|
return [...successEntries, ...errorEntries]
|
|
947
978
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Similar to "nano-universal-deployer" but targets Arachnid's Deterministic Deployment Proxy
|
|
2
|
+
# (a CREATE2 deployer available at 0x4e59… on every chain). The proxy call reverts when the
|
|
3
|
+
# inner CREATE2 fails, so no additional assurance wrapper is needed.
|
|
4
|
+
name: "arachnid-deterministic-deployment-proxy"
|
|
5
|
+
type: "template"
|
|
6
|
+
description: "Deploy contracts through Arachnid's Deterministic Deployment Proxy"
|
|
7
|
+
|
|
8
|
+
arguments:
|
|
9
|
+
creationCode:
|
|
10
|
+
type: "bytes"
|
|
11
|
+
description: "Creation code of the contract to deploy"
|
|
12
|
+
salt:
|
|
13
|
+
type: "bytes32"
|
|
14
|
+
description: "Salt supplied to the proxy for CREATE2"
|
|
15
|
+
|
|
16
|
+
returns:
|
|
17
|
+
address:
|
|
18
|
+
type: "address"
|
|
19
|
+
description: "Address of the deployed contract"
|
|
20
|
+
|
|
21
|
+
setup:
|
|
22
|
+
skip_condition:
|
|
23
|
+
- type: "contract-exists"
|
|
24
|
+
arguments:
|
|
25
|
+
address: "0x4e59b44847b379578588920ca78fbf26c0b4956c"
|
|
26
|
+
actions:
|
|
27
|
+
- type: "test-nicks-method"
|
|
28
|
+
- type: "min-balance"
|
|
29
|
+
arguments:
|
|
30
|
+
address: "0x3fab184622dc19b6109349b94811493bf2a45362"
|
|
31
|
+
balance: "10000000000000000"
|
|
32
|
+
- type: "send-signed-transaction"
|
|
33
|
+
arguments:
|
|
34
|
+
transaction: |
|
|
35
|
+
0xf8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222
|
|
36
|
+
|
|
37
|
+
actions:
|
|
38
|
+
- type: "send-transaction"
|
|
39
|
+
arguments:
|
|
40
|
+
to: "0x4e59b44847b379578588920ca78fbf26c0b4956c"
|
|
41
|
+
data:
|
|
42
|
+
type: "abi-pack"
|
|
43
|
+
arguments:
|
|
44
|
+
types:
|
|
45
|
+
- "bytes32"
|
|
46
|
+
- "bytes"
|
|
47
|
+
values:
|
|
48
|
+
- "{{salt}}"
|
|
49
|
+
- "{{creationCode}}"
|
|
50
|
+
gasMultiplier: 1.6
|
|
51
|
+
|
|
52
|
+
skip_condition:
|
|
53
|
+
- type: "contract-exists"
|
|
54
|
+
arguments:
|
|
55
|
+
address:
|
|
56
|
+
type: "compute-create2"
|
|
57
|
+
arguments:
|
|
58
|
+
deployerAddress: "0x4e59b44847b379578588920ca78fbf26c0b4956c"
|
|
59
|
+
salt: "{{salt}}"
|
|
60
|
+
initCode: "{{creationCode}}"
|
|
61
|
+
|
|
62
|
+
outputs:
|
|
63
|
+
address:
|
|
64
|
+
type: "compute-create2"
|
|
65
|
+
arguments:
|
|
66
|
+
deployerAddress: "0x4e59b44847b379578588920ca78fbf26c0b4956c"
|
|
67
|
+
salt: "{{salt}}"
|
|
68
|
+
initCode: "{{creationCode}}"
|