gate-evm-tools 1.0.26 → 1.0.28

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 (338) hide show
  1. package/README.md +14 -0
  2. package/bin/workflow.cjs +19 -0
  3. package/dist/core/BytecodeChecker.d.ts.map +1 -1
  4. package/dist/core/BytecodeChecker.js +16 -1
  5. package/dist/core/BytecodeChecker.js.map +1 -1
  6. package/dist/core/legacyProxyArtifact.d.ts +6 -0
  7. package/dist/core/legacyProxyArtifact.d.ts.map +1 -0
  8. package/dist/core/legacyProxyArtifact.js +36 -0
  9. package/dist/core/legacyProxyArtifact.js.map +1 -0
  10. package/dist-runtime/config/hardhatAdapters.d.ts +7 -0
  11. package/dist-runtime/config/hardhatAdapters.js +61 -0
  12. package/dist-runtime/config/hardhatAdapters.js.map +1 -0
  13. package/dist-runtime/config/networks.d.ts +32 -0
  14. package/dist-runtime/config/networks.js +275 -0
  15. package/dist-runtime/config/networks.js.map +1 -0
  16. package/dist-runtime/config/openzeppelin.d.ts +28 -0
  17. package/dist-runtime/config/openzeppelin.js +144 -0
  18. package/dist-runtime/config/openzeppelin.js.map +1 -0
  19. package/dist-runtime/config/rpc.d.ts +7 -0
  20. package/dist-runtime/config/rpc.js +19 -0
  21. package/dist-runtime/config/rpc.js.map +1 -0
  22. package/dist-runtime/config/zksyncSolcPath.d.ts +1 -0
  23. package/dist-runtime/config/zksyncSolcPath.js +61 -0
  24. package/dist-runtime/config/zksyncSolcPath.js.map +1 -0
  25. package/dist-runtime/migrate.d.ts +13 -0
  26. package/dist-runtime/migrate.js +208 -0
  27. package/dist-runtime/migrate.js.map +1 -0
  28. package/dist-runtime/package.json +1 -0
  29. package/dist-runtime/projectHardhat.d.ts +4 -0
  30. package/dist-runtime/projectHardhat.js +16 -0
  31. package/dist-runtime/projectHardhat.js.map +1 -0
  32. package/dist-runtime/runtime-identity.json +4 -0
  33. package/dist-runtime/template-migration.json +293 -0
  34. package/dist-runtime/workflow/checkCode.d.ts +1 -0
  35. package/dist-runtime/workflow/checkCode.js +16 -0
  36. package/dist-runtime/workflow/checkCode.js.map +1 -0
  37. package/dist-runtime/workflow/checkCodeFinalize.d.ts +1 -0
  38. package/dist-runtime/workflow/checkCodeFinalize.js +11 -0
  39. package/dist-runtime/workflow/checkCodeFinalize.js.map +1 -0
  40. package/dist-runtime/workflow/checkCodePlan.d.ts +1 -0
  41. package/dist-runtime/workflow/checkCodePlan.js +11 -0
  42. package/dist-runtime/workflow/checkCodePlan.js.map +1 -0
  43. package/dist-runtime/workflow/cli.d.ts +1 -0
  44. package/dist-runtime/workflow/cli.js +302 -0
  45. package/dist-runtime/workflow/cli.js.map +1 -0
  46. package/dist-runtime/workflow/commitContractInfo.d.ts +1 -0
  47. package/dist-runtime/workflow/commitContractInfo.js +64 -0
  48. package/dist-runtime/workflow/commitContractInfo.js.map +1 -0
  49. package/dist-runtime/workflow/create2Hashes.d.ts +1 -0
  50. package/dist-runtime/workflow/create2Hashes.js +76 -0
  51. package/dist-runtime/workflow/create2Hashes.js.map +1 -0
  52. package/dist-runtime/workflow/forkSourceProxy.d.ts +1 -0
  53. package/dist-runtime/workflow/forkSourceProxy.js +151 -0
  54. package/dist-runtime/workflow/forkSourceProxy.js.map +1 -0
  55. package/dist-runtime/workflow/importState.d.ts +1 -0
  56. package/dist-runtime/workflow/importState.js +193 -0
  57. package/dist-runtime/workflow/importState.js.map +1 -0
  58. package/dist-runtime/workflow/lib/authority.d.ts +28 -0
  59. package/dist-runtime/workflow/lib/authority.js +122 -0
  60. package/dist-runtime/workflow/lib/authority.js.map +1 -0
  61. package/dist-runtime/workflow/lib/calldata.d.ts +2 -0
  62. package/dist-runtime/workflow/lib/calldata.js +8 -0
  63. package/dist-runtime/workflow/lib/calldata.js.map +1 -0
  64. package/dist-runtime/workflow/lib/calls.d.ts +23 -0
  65. package/dist-runtime/workflow/lib/calls.js +316 -0
  66. package/dist-runtime/workflow/lib/calls.js.map +1 -0
  67. package/dist-runtime/workflow/lib/checkCode/args.d.ts +2 -0
  68. package/dist-runtime/workflow/lib/checkCode/args.js +68 -0
  69. package/dist-runtime/workflow/lib/checkCode/args.js.map +1 -0
  70. package/dist-runtime/workflow/lib/checkCode/command.d.ts +5 -0
  71. package/dist-runtime/workflow/lib/checkCode/command.js +35 -0
  72. package/dist-runtime/workflow/lib/checkCode/command.js.map +1 -0
  73. package/dist-runtime/workflow/lib/checkCode/dependencies.d.ts +6 -0
  74. package/dist-runtime/workflow/lib/checkCode/dependencies.js +125 -0
  75. package/dist-runtime/workflow/lib/checkCode/dependencies.js.map +1 -0
  76. package/dist-runtime/workflow/lib/checkCode/finalize.d.ts +17 -0
  77. package/dist-runtime/workflow/lib/checkCode/finalize.js +174 -0
  78. package/dist-runtime/workflow/lib/checkCode/finalize.js.map +1 -0
  79. package/dist-runtime/workflow/lib/checkCode/index.d.ts +3 -0
  80. package/dist-runtime/workflow/lib/checkCode/index.js +20 -0
  81. package/dist-runtime/workflow/lib/checkCode/index.js.map +1 -0
  82. package/dist-runtime/workflow/lib/checkCode/plan.d.ts +22 -0
  83. package/dist-runtime/workflow/lib/checkCode/plan.js +145 -0
  84. package/dist-runtime/workflow/lib/checkCode/plan.js.map +1 -0
  85. package/dist-runtime/workflow/lib/checkCodeReport.d.ts +25 -0
  86. package/dist-runtime/workflow/lib/checkCodeReport.js +102 -0
  87. package/dist-runtime/workflow/lib/checkCodeReport.js.map +1 -0
  88. package/dist-runtime/workflow/lib/checkCodeRunner.d.ts +87 -0
  89. package/dist-runtime/workflow/lib/checkCodeRunner.js +964 -0
  90. package/dist-runtime/workflow/lib/checkCodeRunner.js.map +1 -0
  91. package/dist-runtime/workflow/lib/cliTool.d.ts +10 -0
  92. package/dist-runtime/workflow/lib/cliTool.js +25 -0
  93. package/dist-runtime/workflow/lib/cliTool.js.map +1 -0
  94. package/dist-runtime/workflow/lib/config.d.ts +33 -0
  95. package/dist-runtime/workflow/lib/config.js +100 -0
  96. package/dist-runtime/workflow/lib/config.js.map +1 -0
  97. package/dist-runtime/workflow/lib/contractInfoCandidates.d.ts +82 -0
  98. package/dist-runtime/workflow/lib/contractInfoCandidates.js +441 -0
  99. package/dist-runtime/workflow/lib/contractInfoCandidates.js.map +1 -0
  100. package/dist-runtime/workflow/lib/controlledMulticallAbi.d.ts +2 -0
  101. package/dist-runtime/workflow/lib/controlledMulticallAbi.js +10 -0
  102. package/dist-runtime/workflow/lib/controlledMulticallAbi.js.map +1 -0
  103. package/dist-runtime/workflow/lib/create2.d.ts +49 -0
  104. package/dist-runtime/workflow/lib/create2.js +194 -0
  105. package/dist-runtime/workflow/lib/create2.js.map +1 -0
  106. package/dist-runtime/workflow/lib/create2Hashes.d.ts +22 -0
  107. package/dist-runtime/workflow/lib/create2Hashes.js +57 -0
  108. package/dist-runtime/workflow/lib/create2Hashes.js.map +1 -0
  109. package/dist-runtime/workflow/lib/deploymentInfo.d.ts +40 -0
  110. package/dist-runtime/workflow/lib/deploymentInfo.js +240 -0
  111. package/dist-runtime/workflow/lib/deploymentInfo.js.map +1 -0
  112. package/dist-runtime/workflow/lib/deploymentRecords.d.ts +137 -0
  113. package/dist-runtime/workflow/lib/deploymentRecords.js +374 -0
  114. package/dist-runtime/workflow/lib/deploymentRecords.js.map +1 -0
  115. package/dist-runtime/workflow/lib/deployments.d.ts +21 -0
  116. package/dist-runtime/workflow/lib/deployments.js +240 -0
  117. package/dist-runtime/workflow/lib/deployments.js.map +1 -0
  118. package/dist-runtime/workflow/lib/erc1967.d.ts +5 -0
  119. package/dist-runtime/workflow/lib/erc1967.js +29 -0
  120. package/dist-runtime/workflow/lib/erc1967.js.map +1 -0
  121. package/dist-runtime/workflow/lib/errors.d.ts +6 -0
  122. package/dist-runtime/workflow/lib/errors.js +77 -0
  123. package/dist-runtime/workflow/lib/errors.js.map +1 -0
  124. package/dist-runtime/workflow/lib/executionId.d.ts +7 -0
  125. package/dist-runtime/workflow/lib/executionId.js +26 -0
  126. package/dist-runtime/workflow/lib/executionId.js.map +1 -0
  127. package/dist-runtime/workflow/lib/executionPlan.d.ts +85 -0
  128. package/dist-runtime/workflow/lib/executionPlan.js +450 -0
  129. package/dist-runtime/workflow/lib/executionPlan.js.map +1 -0
  130. package/dist-runtime/workflow/lib/executionProgress.d.ts +5 -0
  131. package/dist-runtime/workflow/lib/executionProgress.js +100 -0
  132. package/dist-runtime/workflow/lib/executionProgress.js.map +1 -0
  133. package/dist-runtime/workflow/lib/external.d.ts +62 -0
  134. package/dist-runtime/workflow/lib/external.js +282 -0
  135. package/dist-runtime/workflow/lib/external.js.map +1 -0
  136. package/dist-runtime/workflow/lib/externalExecutionScanner.d.ts +64 -0
  137. package/dist-runtime/workflow/lib/externalExecutionScanner.js +638 -0
  138. package/dist-runtime/workflow/lib/externalExecutionScanner.js.map +1 -0
  139. package/dist-runtime/workflow/lib/forkSnapshot.d.ts +34 -0
  140. package/dist-runtime/workflow/lib/forkSnapshot.js +167 -0
  141. package/dist-runtime/workflow/lib/forkSnapshot.js.map +1 -0
  142. package/dist-runtime/workflow/lib/gateTool.d.ts +16 -0
  143. package/dist-runtime/workflow/lib/gateTool.js +177 -0
  144. package/dist-runtime/workflow/lib/gateTool.js.map +1 -0
  145. package/dist-runtime/workflow/lib/gateToolSync.d.ts +22 -0
  146. package/dist-runtime/workflow/lib/gateToolSync.js +253 -0
  147. package/dist-runtime/workflow/lib/gateToolSync.js.map +1 -0
  148. package/dist-runtime/workflow/lib/lock.d.ts +52 -0
  149. package/dist-runtime/workflow/lib/lock.js +269 -0
  150. package/dist-runtime/workflow/lib/lock.js.map +1 -0
  151. package/dist-runtime/workflow/lib/migrationState.d.ts +103 -0
  152. package/dist-runtime/workflow/lib/migrationState.js +920 -0
  153. package/dist-runtime/workflow/lib/migrationState.js.map +1 -0
  154. package/dist-runtime/workflow/lib/operatorExecution.d.ts +28 -0
  155. package/dist-runtime/workflow/lib/operatorExecution.js +134 -0
  156. package/dist-runtime/workflow/lib/operatorExecution.js.map +1 -0
  157. package/dist-runtime/workflow/lib/parameters.d.ts +58 -0
  158. package/dist-runtime/workflow/lib/parameters.js +323 -0
  159. package/dist-runtime/workflow/lib/parameters.js.map +1 -0
  160. package/dist-runtime/workflow/lib/pendingDeploymentReuse.d.ts +29 -0
  161. package/dist-runtime/workflow/lib/pendingDeploymentReuse.js +277 -0
  162. package/dist-runtime/workflow/lib/pendingDeploymentReuse.js.map +1 -0
  163. package/dist-runtime/workflow/lib/proxy.d.ts +18 -0
  164. package/dist-runtime/workflow/lib/proxy.js +19 -0
  165. package/dist-runtime/workflow/lib/proxy.js.map +1 -0
  166. package/dist-runtime/workflow/lib/registryCommit.d.ts +33 -0
  167. package/dist-runtime/workflow/lib/registryCommit.js +319 -0
  168. package/dist-runtime/workflow/lib/registryCommit.js.map +1 -0
  169. package/dist-runtime/workflow/lib/release.d.ts +57 -0
  170. package/dist-runtime/workflow/lib/release.js +256 -0
  171. package/dist-runtime/workflow/lib/release.js.map +1 -0
  172. package/dist-runtime/workflow/lib/releaseFinalize.d.ts +14 -0
  173. package/dist-runtime/workflow/lib/releaseFinalize.js +571 -0
  174. package/dist-runtime/workflow/lib/releaseFinalize.js.map +1 -0
  175. package/dist-runtime/workflow/lib/releaseParameters.d.ts +43 -0
  176. package/dist-runtime/workflow/lib/releaseParameters.js +184 -0
  177. package/dist-runtime/workflow/lib/releaseParameters.js.map +1 -0
  178. package/dist-runtime/workflow/lib/reporter.d.ts +39 -0
  179. package/dist-runtime/workflow/lib/reporter.js +452 -0
  180. package/dist-runtime/workflow/lib/reporter.js.map +1 -0
  181. package/dist-runtime/workflow/lib/resultPaths.d.ts +17 -0
  182. package/dist-runtime/workflow/lib/resultPaths.js +29 -0
  183. package/dist-runtime/workflow/lib/resultPaths.js.map +1 -0
  184. package/dist-runtime/workflow/lib/runtimeVersion.d.ts +10 -0
  185. package/dist-runtime/workflow/lib/runtimeVersion.js +46 -0
  186. package/dist-runtime/workflow/lib/runtimeVersion.js.map +1 -0
  187. package/dist-runtime/workflow/lib/signer.d.ts +10 -0
  188. package/dist-runtime/workflow/lib/signer.js +105 -0
  189. package/dist-runtime/workflow/lib/signer.js.map +1 -0
  190. package/dist-runtime/workflow/lib/signerIdentity.d.ts +1 -0
  191. package/dist-runtime/workflow/lib/signerIdentity.js +23 -0
  192. package/dist-runtime/workflow/lib/signerIdentity.js.map +1 -0
  193. package/dist-runtime/workflow/lib/simulation.d.ts +35 -0
  194. package/dist-runtime/workflow/lib/simulation.js +282 -0
  195. package/dist-runtime/workflow/lib/simulation.js.map +1 -0
  196. package/dist-runtime/workflow/lib/simulationCallers.d.ts +44 -0
  197. package/dist-runtime/workflow/lib/simulationCallers.js +260 -0
  198. package/dist-runtime/workflow/lib/simulationCallers.js.map +1 -0
  199. package/dist-runtime/workflow/lib/sourceRpcPolicy.d.ts +1 -0
  200. package/dist-runtime/workflow/lib/sourceRpcPolicy.js +43 -0
  201. package/dist-runtime/workflow/lib/sourceRpcPolicy.js.map +1 -0
  202. package/dist-runtime/workflow/lib/state.d.ts +6 -0
  203. package/dist-runtime/workflow/lib/state.js +25 -0
  204. package/dist-runtime/workflow/lib/state.js.map +1 -0
  205. package/dist-runtime/workflow/lib/staticValidation.d.ts +22 -0
  206. package/dist-runtime/workflow/lib/staticValidation.js +124 -0
  207. package/dist-runtime/workflow/lib/staticValidation.js.map +1 -0
  208. package/dist-runtime/workflow/lib/zksyncForkCapability.d.ts +27 -0
  209. package/dist-runtime/workflow/lib/zksyncForkCapability.js +52 -0
  210. package/dist-runtime/workflow/lib/zksyncForkCapability.js.map +1 -0
  211. package/dist-runtime/workflow/lib/zksyncForkRunner.d.ts +57 -0
  212. package/dist-runtime/workflow/lib/zksyncForkRunner.js +344 -0
  213. package/dist-runtime/workflow/lib/zksyncForkRunner.js.map +1 -0
  214. package/dist-runtime/workflow/reconcileExternal.d.ts +1 -0
  215. package/dist-runtime/workflow/reconcileExternal.js +87 -0
  216. package/dist-runtime/workflow/reconcileExternal.js.map +1 -0
  217. package/dist-runtime/workflow/reconcileExternalRun.d.ts +1 -0
  218. package/dist-runtime/workflow/reconcileExternalRun.js +77 -0
  219. package/dist-runtime/workflow/reconcileExternalRun.js.map +1 -0
  220. package/dist-runtime/workflow/releaseFinalize.d.ts +1 -0
  221. package/dist-runtime/workflow/releaseFinalize.js +11 -0
  222. package/dist-runtime/workflow/releaseFinalize.js.map +1 -0
  223. package/dist-runtime/workflow/run.d.ts +40 -0
  224. package/dist-runtime/workflow/run.js +858 -0
  225. package/dist-runtime/workflow/run.js.map +1 -0
  226. package/dist-runtime/workflow/staticValidate.d.ts +1 -0
  227. package/dist-runtime/workflow/staticValidate.js +26 -0
  228. package/dist-runtime/workflow/staticValidate.js.map +1 -0
  229. package/dist-runtime/workflow/steps/call.d.ts +3 -0
  230. package/dist-runtime/workflow/steps/call.js +9 -0
  231. package/dist-runtime/workflow/steps/call.js.map +1 -0
  232. package/dist-runtime/workflow/steps/check.d.ts +3 -0
  233. package/dist-runtime/workflow/steps/check.js +9 -0
  234. package/dist-runtime/workflow/steps/check.js.map +1 -0
  235. package/dist-runtime/workflow/steps/custom.d.ts +3 -0
  236. package/dist-runtime/workflow/steps/custom.js +33 -0
  237. package/dist-runtime/workflow/steps/custom.js.map +1 -0
  238. package/dist-runtime/workflow/steps/deploy.d.ts +3 -0
  239. package/dist-runtime/workflow/steps/deploy.js +596 -0
  240. package/dist-runtime/workflow/steps/deploy.js.map +1 -0
  241. package/dist-runtime/workflow/steps/upgrade.d.ts +3 -0
  242. package/dist-runtime/workflow/steps/upgrade.js +466 -0
  243. package/dist-runtime/workflow/steps/upgrade.js.map +1 -0
  244. package/dist-runtime/workflow/steps/view.d.ts +3 -0
  245. package/dist-runtime/workflow/steps/view.js +9 -0
  246. package/dist-runtime/workflow/steps/view.js.map +1 -0
  247. package/docs/direct-package-acceptance.md +20 -0
  248. package/docs/external-infrastructure-acceptance.md +33 -0
  249. package/docs/network-runtime-acceptance.md +18 -0
  250. package/docs/plans/2026-09-09-workflow-extraction.md +16 -0
  251. package/docs/superpowers/plans/2026-07-22-manifest-bootstrap-transaction.md +50 -0
  252. package/docs/superpowers/plans/2026-07-22-manifest-review-remediation.md +49 -0
  253. package/docs/superpowers/plans/2026-08-17-custody-hardhat-signers.md +227 -0
  254. package/docs/superpowers/plans/2026-09-09-remove-template-infrastructure-contracts.md +11 -0
  255. package/docs/workflow-reference.md +1181 -0
  256. package/docs/workflow-runtime-acceptance.md +17 -0
  257. package/docs/workflow-runtime.md +56 -0
  258. package/package.json +26 -5
  259. package/runtime/config/hardhatAdapters.ts +58 -0
  260. package/runtime/config/networks.ts +305 -0
  261. package/runtime/config/openzeppelin.ts +173 -0
  262. package/runtime/config/rpc.ts +27 -0
  263. package/runtime/config/zksyncSolcPath.ts +59 -0
  264. package/runtime/hardhat-types.d.ts +2 -0
  265. package/runtime/migrate.ts +154 -0
  266. package/runtime/projectHardhat.ts +10 -0
  267. package/runtime/template-migration.json +293 -0
  268. package/runtime/workflow/checkCode.ts +13 -0
  269. package/runtime/workflow/checkCodeFinalize.ts +8 -0
  270. package/runtime/workflow/checkCodePlan.ts +8 -0
  271. package/runtime/workflow/cli.ts +356 -0
  272. package/runtime/workflow/commitContractInfo.ts +63 -0
  273. package/runtime/workflow/create2Hashes.ts +79 -0
  274. package/runtime/workflow/forkSourceProxy.ts +193 -0
  275. package/runtime/workflow/importState.ts +190 -0
  276. package/runtime/workflow/lib/authority.ts +170 -0
  277. package/runtime/workflow/lib/calldata.ts +9 -0
  278. package/runtime/workflow/lib/calls.ts +407 -0
  279. package/runtime/workflow/lib/checkCode/args.ts +76 -0
  280. package/runtime/workflow/lib/checkCode/command.ts +36 -0
  281. package/runtime/workflow/lib/checkCode/dependencies.ts +112 -0
  282. package/runtime/workflow/lib/checkCode/finalize.ts +198 -0
  283. package/runtime/workflow/lib/checkCode/index.ts +18 -0
  284. package/runtime/workflow/lib/checkCode/plan.ts +163 -0
  285. package/runtime/workflow/lib/checkCodeReport.ts +133 -0
  286. package/runtime/workflow/lib/checkCodeRunner.ts +1225 -0
  287. package/runtime/workflow/lib/cliTool.ts +31 -0
  288. package/runtime/workflow/lib/config.ts +130 -0
  289. package/runtime/workflow/lib/contractInfoCandidates.ts +690 -0
  290. package/runtime/workflow/lib/controlledMulticallAbi.ts +6 -0
  291. package/runtime/workflow/lib/create2.ts +278 -0
  292. package/runtime/workflow/lib/create2Hashes.ts +83 -0
  293. package/runtime/workflow/lib/deploymentInfo.ts +286 -0
  294. package/runtime/workflow/lib/deploymentRecords.ts +576 -0
  295. package/runtime/workflow/lib/deployments.ts +276 -0
  296. package/runtime/workflow/lib/erc1967.ts +57 -0
  297. package/runtime/workflow/lib/errors.ts +95 -0
  298. package/runtime/workflow/lib/executionId.ts +35 -0
  299. package/runtime/workflow/lib/executionPlan.ts +550 -0
  300. package/runtime/workflow/lib/executionProgress.ts +127 -0
  301. package/runtime/workflow/lib/external.ts +372 -0
  302. package/runtime/workflow/lib/externalExecutionScanner.ts +892 -0
  303. package/runtime/workflow/lib/forkSnapshot.ts +231 -0
  304. package/runtime/workflow/lib/gateTool.ts +261 -0
  305. package/runtime/workflow/lib/gateToolSync.ts +398 -0
  306. package/runtime/workflow/lib/lock.ts +388 -0
  307. package/runtime/workflow/lib/migrationState.ts +1246 -0
  308. package/runtime/workflow/lib/operatorExecution.ts +174 -0
  309. package/runtime/workflow/lib/parameters.ts +438 -0
  310. package/runtime/workflow/lib/pendingDeploymentReuse.ts +428 -0
  311. package/runtime/workflow/lib/proxy.ts +45 -0
  312. package/runtime/workflow/lib/registryCommit.ts +455 -0
  313. package/runtime/workflow/lib/release.ts +329 -0
  314. package/runtime/workflow/lib/releaseFinalize.ts +711 -0
  315. package/runtime/workflow/lib/releaseParameters.ts +248 -0
  316. package/runtime/workflow/lib/reporter.ts +502 -0
  317. package/runtime/workflow/lib/resultPaths.ts +49 -0
  318. package/runtime/workflow/lib/runtimeVersion.ts +28 -0
  319. package/runtime/workflow/lib/signer.ts +124 -0
  320. package/runtime/workflow/lib/signerIdentity.ts +22 -0
  321. package/runtime/workflow/lib/simulation.ts +415 -0
  322. package/runtime/workflow/lib/simulationCallers.ts +335 -0
  323. package/runtime/workflow/lib/sourceRpcPolicy.ts +41 -0
  324. package/runtime/workflow/lib/state.ts +25 -0
  325. package/runtime/workflow/lib/staticValidation.ts +142 -0
  326. package/runtime/workflow/lib/zksyncForkCapability.ts +80 -0
  327. package/runtime/workflow/lib/zksyncForkRunner.ts +505 -0
  328. package/runtime/workflow/reconcileExternal.ts +86 -0
  329. package/runtime/workflow/reconcileExternalRun.ts +88 -0
  330. package/runtime/workflow/releaseFinalize.ts +8 -0
  331. package/runtime/workflow/run.ts +1072 -0
  332. package/runtime/workflow/staticValidate.ts +23 -0
  333. package/runtime/workflow/steps/call.ts +10 -0
  334. package/runtime/workflow/steps/check.ts +10 -0
  335. package/runtime/workflow/steps/custom.ts +43 -0
  336. package/runtime/workflow/steps/deploy.ts +772 -0
  337. package/runtime/workflow/steps/upgrade.ts +599 -0
  338. package/runtime/workflow/steps/view.ts +10 -0
@@ -0,0 +1,502 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { readJsonFile, writeJsonFile } from "./config";
4
+ import { WorkflowMode } from "./simulation";
5
+ import {
6
+ WORKFLOW_RESULT_NAMES,
7
+ WorkflowResultName,
8
+ workflowResultRelativeDirectory,
9
+ workflowResultRelativePath,
10
+ } from "./resultPaths";
11
+
12
+ const RUNTIME_STATUS_FIELDS = [
13
+ "blockedReasons",
14
+ "errorType",
15
+ "retryable",
16
+ "message",
17
+ "stepId",
18
+ "simulationResult",
19
+ "planResult",
20
+ ] as const;
21
+ const STATUS_LOCK_STALE_MS = 30_000;
22
+ const STATUS_LOCK_WAIT_MS = 35_000;
23
+ const STATUS_LOCK_POLL_MS = 10;
24
+ const STATUS_LOCK_SLEEP = new Int32Array(new SharedArrayBuffer(4));
25
+
26
+ const isNonZeroEvmAddress = (value: unknown): value is string => {
27
+ return typeof value === "string"
28
+ && /^0x[0-9a-fA-F]{40}$/.test(value)
29
+ && value.toLowerCase() !== "0x0000000000000000000000000000000000000000";
30
+ };
31
+
32
+ export class WorkflowReporter {
33
+ private readonly initializedResults = new Set<WorkflowResultName>();
34
+ private simulationCallerAddress?: string;
35
+
36
+ constructor(
37
+ private readonly taskDir: string,
38
+ private readonly taskId: string,
39
+ private readonly executionId: string,
40
+ private readonly targetId: string,
41
+ private readonly mode: WorkflowMode = "execute",
42
+ ) {}
43
+
44
+ initializeResults(names: readonly WorkflowResultName[] = WORKFLOW_RESULT_NAMES): void {
45
+ const directory = this.resultDirectoryPath();
46
+ fs.mkdirSync(path.dirname(directory), { recursive: true });
47
+ try {
48
+ fs.mkdirSync(directory);
49
+ } catch (error) {
50
+ if ((error as NodeJS.ErrnoException).code !== "EEXIST") throw error;
51
+ this.retryFailedVerification(directory, names);
52
+ return;
53
+ }
54
+
55
+ this.writeInitialResults(names);
56
+ }
57
+
58
+ private writeInitialResults(names: readonly WorkflowResultName[]): void {
59
+ for (const name of names) {
60
+ writeJsonFile(this.resultPath(name), this.resultEnvelope([]));
61
+ this.initializedResults.add(name);
62
+ }
63
+ }
64
+
65
+ private retryFailedVerification(
66
+ directory: string,
67
+ names: readonly WorkflowResultName[],
68
+ ): void {
69
+ const claimedError = (): Error => new Error(
70
+ `Workflow result namespace already claimed for target "${this.targetId}", executionId "${this.executionId}", mode "${this.mode}"; use a new executionId`,
71
+ );
72
+ if (this.mode === "execute" && this.resumeSegmentedAdminExecution(names)) return;
73
+ if (this.mode !== "verify") throw claimedError();
74
+
75
+ const parent = path.dirname(directory);
76
+ const lockPath = path.join(parent, ".verify-retry.lock");
77
+ let lock: number;
78
+ try {
79
+ lock = fs.openSync(lockPath, "wx");
80
+ } catch {
81
+ throw claimedError();
82
+ }
83
+
84
+ let archivePath: string | undefined;
85
+ try {
86
+ const status = this.readStatusFile(path.join(this.taskDir, "status.json"));
87
+ const networkStatus = status.networks?.[this.targetId];
88
+ if (
89
+ networkStatus?.lastExecutionId !== this.executionId
90
+ || networkStatus.lastExecutionMode !== "verify"
91
+ || networkStatus.verifyStatus !== "failed"
92
+ ) {
93
+ throw claimedError();
94
+ }
95
+
96
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
97
+ const archiveBase = path.join(parent, `verify.failed.${timestamp}`);
98
+ archivePath = archiveBase;
99
+ for (let suffix = 1; fs.existsSync(archivePath); suffix += 1) {
100
+ archivePath = `${archiveBase}.${suffix}`;
101
+ }
102
+ fs.renameSync(directory, archivePath);
103
+ fs.mkdirSync(directory);
104
+ this.writeInitialResults(names);
105
+ this.status("running", { mode: this.mode });
106
+ } catch (error) {
107
+ if (archivePath && fs.existsSync(archivePath)) {
108
+ fs.rmSync(directory, { recursive: true, force: true });
109
+ fs.renameSync(archivePath, directory);
110
+ }
111
+ throw error;
112
+ } finally {
113
+ fs.closeSync(lock);
114
+ fs.unlinkSync(lockPath);
115
+ }
116
+ }
117
+
118
+ private resumeSegmentedAdminExecution(names: readonly WorkflowResultName[]): boolean {
119
+ const executionRoot = path.join(
120
+ this.taskDir,
121
+ "results",
122
+ this.targetId,
123
+ this.executionId,
124
+ );
125
+ const planPath = path.join(executionRoot, "execution-plan.json");
126
+ const reconciliationPath = path.join(executionRoot, "external-reconciliation.json");
127
+ if (!fs.existsSync(planPath) || !fs.existsSync(reconciliationPath)) return false;
128
+ let plan: Record<string, unknown>;
129
+ let reconciliation: Record<string, unknown>;
130
+ try {
131
+ plan = readJsonFile<Record<string, unknown>>(planPath);
132
+ reconciliation = readJsonFile<Record<string, unknown>>(reconciliationPath);
133
+ } catch {
134
+ return false;
135
+ }
136
+ const status = this.readStatusFile(path.join(this.taskDir, "status.json"));
137
+ const networkStatus = status.networks?.[this.targetId];
138
+ if (
139
+ plan.version !== 1
140
+ || plan.taskId !== this.taskId
141
+ || plan.target !== this.targetId
142
+ || plan.executionId !== this.executionId
143
+ || plan.releaseKind !== "admin_release"
144
+ || typeof plan.planHash !== "string"
145
+ || reconciliation.version !== 1
146
+ || reconciliation.status !== "waiting_operator"
147
+ || reconciliation.taskId !== this.taskId
148
+ || reconciliation.target !== this.targetId
149
+ || reconciliation.executionId !== this.executionId
150
+ || reconciliation.executionPlanHash !== plan.planHash
151
+ || networkStatus?.lastExecutionId !== this.executionId
152
+ || networkStatus.lastExecutionMode !== "execute"
153
+ ) {
154
+ return false;
155
+ }
156
+ for (const name of names) {
157
+ if (!fs.existsSync(this.resultPath(name))) return false;
158
+ const result = readJsonFile<Record<string, unknown>>(this.resultPath(name));
159
+ if (
160
+ result.taskId !== this.taskId
161
+ || result.executionId !== this.executionId
162
+ || result.target !== this.targetId
163
+ || result.mode !== "execute"
164
+ || !Array.isArray(result.steps)
165
+ ) {
166
+ return false;
167
+ }
168
+ this.initializedResults.add(name);
169
+ }
170
+ return true;
171
+ }
172
+
173
+ event(type: string, payload: Record<string, unknown> = {}): void {
174
+ const filePath = path.join(this.taskDir, "events.jsonl");
175
+ fs.appendFileSync(
176
+ filePath,
177
+ `${JSON.stringify({
178
+ taskId: this.taskId,
179
+ executionId: this.executionId,
180
+ target: this.targetId,
181
+ mode: this.mode,
182
+ type,
183
+ timestamp: new Date().toISOString(),
184
+ ...payload,
185
+ })}\n`,
186
+ );
187
+ }
188
+
189
+ status(status: string, payload: Record<string, unknown> = {}): void {
190
+ const filePath = path.join(this.taskDir, "status.json");
191
+ this.withStatusFileLock(filePath, () => {
192
+ const existing = this.readStatusFile(filePath);
193
+ const baseStatus = this.clearRuntimeStatusFields(existing);
194
+ const targetNetworks = this.targetNetworks(existing);
195
+ const networks = {
196
+ ...(existing.networks || {}),
197
+ [this.targetId]: this.updateNetworkStatus(
198
+ existing.networks?.[this.targetId] || {},
199
+ status,
200
+ ),
201
+ };
202
+
203
+ writeJsonFile(filePath, {
204
+ ...baseStatus,
205
+ targetNetworks,
206
+ networks,
207
+ status: this.globalStatus(status, targetNetworks, networks),
208
+ target: this.targetId,
209
+ executionId: this.executionId,
210
+ mode: this.mode,
211
+ updatedAt: new Date().toISOString(),
212
+ ...payload,
213
+ });
214
+ });
215
+ }
216
+
217
+ result(name: WorkflowResultName, payload: Record<string, unknown>): void {
218
+ if (!this.initializedResults.has(name)) {
219
+ throw new Error(`Workflow result ${name} was not initialized for this execution`);
220
+ }
221
+ const filePath = this.resultPath(name);
222
+ const existing = readJsonFile<{ steps?: unknown }>(filePath);
223
+ if (!Array.isArray(existing.steps)) {
224
+ throw new Error(`Workflow result ${name} has an invalid steps array`);
225
+ }
226
+
227
+ writeJsonFile(filePath, this.resultEnvelope([
228
+ ...(existing.steps as Record<string, unknown>[]),
229
+ {
230
+ timestamp: new Date().toISOString(),
231
+ ...payload,
232
+ ...(this.simulationCallerAddress
233
+ ? { simulationCallerAddress: this.simulationCallerAddress }
234
+ : {}),
235
+ },
236
+ ]));
237
+ this.initializedResults.add(name);
238
+ }
239
+
240
+ setSimulationCallerAddress(callerAddress: string): void {
241
+ if (this.mode !== "simulate" || !isNonZeroEvmAddress(callerAddress)) {
242
+ throw new Error("Simulation caller scope requires a valid simulate-mode address");
243
+ }
244
+ this.simulationCallerAddress = callerAddress;
245
+ }
246
+
247
+ clearSimulationCallerAddress(): void {
248
+ this.simulationCallerAddress = undefined;
249
+ }
250
+
251
+ simulationExecutionResultPath(expected: string | {
252
+ simulationCallerNetworkHash: string;
253
+ simulationCallers: Array<{ stepId: string; callerAddress: string }>;
254
+ }): string {
255
+ if (this.mode !== "simulate") {
256
+ throw new Error("Simulation execution results require simulate mode");
257
+ }
258
+ const result = readJsonFile<{
259
+ executionId?: unknown;
260
+ target?: unknown;
261
+ mode?: unknown;
262
+ steps?: unknown;
263
+ }>(this.resultPath("execution"));
264
+ if (
265
+ result.executionId !== this.executionId
266
+ || result.target !== this.targetId
267
+ || result.mode !== "simulate"
268
+ || !Array.isArray(result.steps)
269
+ ) {
270
+ throw new Error("Simulation execution result does not match this workflow run");
271
+ }
272
+ const terminal = result.steps.at(-1) as Record<string, unknown> | undefined;
273
+ if (
274
+ terminal?.kind !== "workflow-simulation-completed"
275
+ || terminal.status !== "succeeded"
276
+ || !Array.isArray(terminal.selectedStepIds)
277
+ || terminal.selectedStepIds.length === 0
278
+ ) {
279
+ throw new Error("Simulation execution result is missing canonical completion evidence");
280
+ }
281
+ if (typeof expected === "string") {
282
+ if (
283
+ !isNonZeroEvmAddress(terminal.signerAddress)
284
+ || !isNonZeroEvmAddress(expected)
285
+ || terminal.signerAddress.toLowerCase() !== expected.toLowerCase()
286
+ ) {
287
+ throw new Error("Simulation execution result is missing canonical completion evidence");
288
+ }
289
+ } else {
290
+ const actualCallers = terminal.simulationCallers;
291
+ if (
292
+ !/^[0-9a-f]{64}$/.test(expected.simulationCallerNetworkHash)
293
+ || terminal.simulationCallerNetworkHash !== expected.simulationCallerNetworkHash
294
+ || terminal.signerAddress !== undefined
295
+ || !Array.isArray(actualCallers)
296
+ || actualCallers.length !== expected.simulationCallers.length
297
+ || expected.simulationCallers.some((caller, index) => {
298
+ const actual = actualCallers[index] as Record<string, unknown> | undefined;
299
+ return !actual
300
+ || actual.stepId !== caller.stepId
301
+ || !isNonZeroEvmAddress(actual.callerAddress)
302
+ || actual.callerAddress.toLowerCase() !== caller.callerAddress.toLowerCase();
303
+ })
304
+ ) {
305
+ throw new Error("Simulation execution result is missing canonical caller completion evidence");
306
+ }
307
+ }
308
+ return workflowResultRelativePath({
309
+ target: this.targetId,
310
+ executionId: this.executionId,
311
+ mode: this.mode,
312
+ name: "execution",
313
+ });
314
+ }
315
+
316
+ clearSimulationCompletionEvidence(): void {
317
+ if (this.mode !== "simulate") return;
318
+ const filePath = this.resultPath("execution");
319
+ if (!fs.existsSync(filePath)) return;
320
+ const result = readJsonFile<{ steps?: unknown }>(filePath);
321
+ if (!Array.isArray(result.steps)) return;
322
+ const terminal = result.steps.at(-1) as Record<string, unknown> | undefined;
323
+ if (terminal?.kind !== "workflow-simulation-completed") return;
324
+ writeJsonFile(
325
+ filePath,
326
+ this.resultEnvelope(result.steps.slice(0, -1) as Record<string, unknown>[]),
327
+ );
328
+ }
329
+
330
+ report(name: string, lines: string[]): void {
331
+ const filePath = path.join(this.taskDir, "docs", name);
332
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
333
+ fs.writeFileSync(filePath, `${lines.join("\n")}\n`);
334
+ }
335
+
336
+ private readStatusFile(filePath: string): {
337
+ status?: string;
338
+ targetNetworks?: string[];
339
+ networks?: Record<string, Record<string, unknown>>;
340
+ [key: string]: unknown;
341
+ } {
342
+ if (!fs.existsSync(filePath)) return {};
343
+ try {
344
+ const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
345
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
346
+ return parsed as {
347
+ status?: string;
348
+ targetNetworks?: string[];
349
+ networks?: Record<string, Record<string, unknown>>;
350
+ [key: string]: unknown;
351
+ };
352
+ } catch {
353
+ return {};
354
+ }
355
+ }
356
+
357
+ private withStatusFileLock<T>(filePath: string, operation: () => T): T {
358
+ const lockPath = `${filePath}.lock`;
359
+ const token = `${process.pid}:${Date.now()}:${Math.random().toString(16).slice(2)}`;
360
+ const deadline = Date.now() + STATUS_LOCK_WAIT_MS;
361
+ while (true) {
362
+ let descriptor: number | undefined;
363
+ try {
364
+ descriptor = fs.openSync(lockPath, "wx");
365
+ fs.writeFileSync(descriptor, `${token}\n`);
366
+ fs.fsyncSync(descriptor);
367
+ fs.closeSync(descriptor);
368
+ descriptor = undefined;
369
+ break;
370
+ } catch (error) {
371
+ if (descriptor !== undefined) fs.closeSync(descriptor);
372
+ if ((error as NodeJS.ErrnoException).code !== "EEXIST") throw error;
373
+ try {
374
+ if (Date.now() - fs.statSync(lockPath).mtimeMs > STATUS_LOCK_STALE_MS) {
375
+ fs.unlinkSync(lockPath);
376
+ continue;
377
+ }
378
+ } catch (lockError) {
379
+ if ((lockError as NodeJS.ErrnoException).code === "ENOENT") continue;
380
+ throw lockError;
381
+ }
382
+ if (Date.now() >= deadline) {
383
+ throw new Error(`Timed out waiting for task status lock: ${lockPath}`);
384
+ }
385
+ Atomics.wait(STATUS_LOCK_SLEEP, 0, 0, STATUS_LOCK_POLL_MS);
386
+ }
387
+ }
388
+
389
+ try {
390
+ return operation();
391
+ } finally {
392
+ try {
393
+ if (fs.readFileSync(lockPath, "utf8").trim() === token) fs.unlinkSync(lockPath);
394
+ } catch (error) {
395
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
396
+ }
397
+ }
398
+ }
399
+
400
+ private resultEnvelope(steps: Record<string, unknown>[]): Record<string, unknown> {
401
+ return {
402
+ taskId: this.taskId,
403
+ executionId: this.executionId,
404
+ target: this.targetId,
405
+ mode: this.mode,
406
+ updatedAt: new Date().toISOString(),
407
+ steps,
408
+ };
409
+ }
410
+
411
+ private resultPath(name: WorkflowResultName): string {
412
+ return path.join(this.taskDir, workflowResultRelativePath({
413
+ target: this.targetId,
414
+ executionId: this.executionId,
415
+ mode: this.mode,
416
+ name,
417
+ }));
418
+ }
419
+
420
+ private resultDirectoryPath(): string {
421
+ return path.join(this.taskDir, workflowResultRelativeDirectory({
422
+ target: this.targetId,
423
+ executionId: this.executionId,
424
+ mode: this.mode,
425
+ }));
426
+ }
427
+
428
+ private clearRuntimeStatusFields<T extends Record<string, unknown>>(status: T): T {
429
+ const next = { ...status };
430
+ for (const field of RUNTIME_STATUS_FIELDS) {
431
+ delete next[field];
432
+ }
433
+ return next as T;
434
+ }
435
+
436
+ private targetNetworks(existing: { targetNetworks?: string[]; networks?: Record<string, unknown> }): string[] {
437
+ if (Array.isArray(existing.targetNetworks) && existing.targetNetworks.length > 0) {
438
+ return existing.targetNetworks.map((item) => String(item));
439
+ }
440
+ const networkKeys = existing.networks ? Object.keys(existing.networks) : [];
441
+ return Array.from(new Set([...networkKeys, this.targetId]));
442
+ }
443
+
444
+ private updateNetworkStatus(
445
+ current: Record<string, unknown>,
446
+ status: string,
447
+ ): Record<string, unknown> {
448
+ const next = {
449
+ ...current,
450
+ lastExecutionId: this.executionId,
451
+ lastExecutionMode: this.mode,
452
+ updatedAt: new Date().toISOString(),
453
+ };
454
+
455
+ if (this.mode === "simulate") {
456
+ return {
457
+ ...next,
458
+ simulationStatus: status === "completed" ? "succeeded" : status,
459
+ };
460
+ }
461
+
462
+ if (this.mode === "verify") {
463
+ if (status === "completed") return { ...next, verifyStatus: "verified" };
464
+ if (status === "failed") return { ...next, verifyStatus: "failed" };
465
+ if (status === "running") return { ...next, verifyStatus: "running" };
466
+ return next;
467
+ }
468
+
469
+ if (status === "completed") {
470
+ return { ...next, deployStatus: "deployed" };
471
+ }
472
+ if (status === "waiting_external") {
473
+ return { ...next, deployStatus: "waiting_external" };
474
+ }
475
+ if (status === "waiting_code_check") {
476
+ return { ...next, deployStatus: "waiting_code_check" };
477
+ }
478
+ if (status === "failed") {
479
+ return { ...next, deployStatus: "failed" };
480
+ }
481
+ return next;
482
+ }
483
+
484
+ private globalStatus(
485
+ fallback: string,
486
+ targetNetworks: string[],
487
+ networks: Record<string, Record<string, unknown>>,
488
+ ): string {
489
+ if (fallback === "waiting_external") return "externalPending";
490
+ if (fallback !== "completed") return fallback;
491
+ if (this.mode === "simulate") return "simulated";
492
+ const targetStates = targetNetworks.map((network) => networks[network] || {});
493
+ const verifiedCount = targetStates.filter((state) => state.verifyStatus === "verified").length;
494
+ if (verifiedCount === targetNetworks.length && targetNetworks.length > 0) return "verified";
495
+ if (verifiedCount > 0) return "partiallyVerified";
496
+
497
+ const deployedCount = targetStates.filter((state) => state.deployStatus === "deployed").length;
498
+ if (deployedCount === targetNetworks.length && targetNetworks.length > 0) return "deployed";
499
+ if (deployedCount > 0) return "partiallyDeployed";
500
+ return fallback;
501
+ }
502
+ }
@@ -0,0 +1,49 @@
1
+ import path from "path";
2
+ import type { WorkflowMode } from "./simulation";
3
+ import { validateExecutionId } from "./executionId";
4
+
5
+ export const WORKFLOW_RESULT_NAMES = ["execution", "view", "verification"] as const;
6
+
7
+ export type WorkflowResultName = typeof WORKFLOW_RESULT_NAMES[number];
8
+
9
+ interface WorkflowResultPathInput {
10
+ target: string;
11
+ executionId: string;
12
+ mode: WorkflowMode;
13
+ name: WorkflowResultName;
14
+ }
15
+
16
+ interface WorkflowResultDirectoryInput {
17
+ target: string;
18
+ executionId: string;
19
+ mode: WorkflowMode;
20
+ }
21
+
22
+ const SAFE_SEGMENT = /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9_-])?$/;
23
+
24
+ const confinedSegment = (value: string, label: string): string => {
25
+ if (!SAFE_SEGMENT.test(value)) {
26
+ throw new Error(`${label} is not safe for a workflow result path`);
27
+ }
28
+ return value;
29
+ };
30
+
31
+ const modeSegment = (mode: WorkflowMode): string => {
32
+ return mode === "simulate" ? "simulation" : mode;
33
+ };
34
+
35
+ export const workflowResultRelativeDirectory = (
36
+ input: WorkflowResultDirectoryInput,
37
+ ): string => {
38
+ return path.posix.join(
39
+ "results",
40
+ confinedSegment(input.target, "target"),
41
+ validateExecutionId(input.executionId),
42
+ modeSegment(input.mode),
43
+ );
44
+ };
45
+
46
+ export const workflowResultRelativePath = (input: WorkflowResultPathInput): string => {
47
+ const name = confinedSegment(input.name, "result name");
48
+ return path.posix.join(workflowResultRelativeDirectory(input), `${name}.json`);
49
+ };
@@ -0,0 +1,28 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ export interface RuntimeIdentity { version: string; digest: string }
4
+ export function bindExecutionRuntime(input: {taskDir: string; target: string; executionId: string; identity?: RuntimeIdentity}): void {
5
+ if (!/^[A-Za-z0-9][A-Za-z0-9_.-]*$/.test(input.target) || !/^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(input.executionId)) throw new Error('Invalid runtime binding identity');
6
+ const identity: RuntimeIdentity = input.identity ?? JSON.parse(fs.readFileSync(path.join(__dirname, '../../runtime-identity.json'), 'utf8'));
7
+ const dir = path.join(input.taskDir, 'runtime-bindings');
8
+ const file = path.join(dir, `${input.target}.${input.executionId}.json`);
9
+ const verify = () => {
10
+ const saved = JSON.parse(fs.readFileSync(file, 'utf8'));
11
+ if (saved.version !== identity.version || saved.digest !== identity.digest) throw new Error('Workflow runtime version mismatch: restore the pinned package or prepare a new execution; signed state cannot be silently migrated');
12
+ };
13
+ if (fs.existsSync(file)) { verify(); return; }
14
+ const results = path.join(input.taskDir, 'results');
15
+ const prefix = `${input.target}.${input.executionId}.`;
16
+ const legacyResults = fs.existsSync(path.join(results, input.target, input.executionId))
17
+ || (fs.existsSync(results) && fs.readdirSync(results).some(name => name.startsWith(prefix)));
18
+ const lockPath = path.join(input.taskDir, 'parameters.lock.json');
19
+ let legacyLock = false;
20
+ if (fs.existsSync(lockPath)) {
21
+ const contains = (value: unknown): boolean => !!value && typeof value === 'object' && (Object.hasOwn(value, input.executionId) || Object.entries(value).some(([key, item]) => (key === 'executionId' && item === input.executionId) || contains(item)));
22
+ legacyLock = contains(JSON.parse(fs.readFileSync(lockPath, 'utf8')));
23
+ }
24
+ if (legacyResults || legacyLock) throw new Error('Legacy execution has no runtime binding: continue with its original scripts or prepare a new execution after reconciling completed transactions');
25
+ fs.mkdirSync(dir, {recursive:true});
26
+ try { fs.writeFileSync(file, JSON.stringify(identity, null, 2)+'\n', {flag:'wx'}); }
27
+ catch (error) { if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error; verify(); }
28
+ }
@@ -0,0 +1,124 @@
1
+ import { getAddress, isAddress, ZeroAddress } from "ethers";
2
+ import type { Signer } from "ethers";
3
+ import {
4
+ createSigner,
5
+ createZkSyncNodeSigner,
6
+ createZkSyncSigner,
7
+ resolveWalletCredential,
8
+ } from "gate-evm-tools/custody";
9
+ import { ethers, network } from "../../projectHardhat";
10
+ import { assertExecutionSignerAddress } from "./signerIdentity";
11
+ import type { WorkflowMode } from "./simulation";
12
+
13
+ const SIMULATION_SIGNER_BALANCE = "0x3635C9ADC5DEA00000";
14
+
15
+ export interface WorkflowSignerOptions {
16
+ explicitAddress?: string;
17
+ taskAddress?: string;
18
+ useLock?: boolean;
19
+ }
20
+
21
+ const normalizedSimulationAddress = (value: string | undefined): string | undefined => {
22
+ if (value === undefined) return undefined;
23
+ const candidate = value.trim();
24
+ if (!isAddress(candidate) || getAddress(candidate) === ZeroAddress) {
25
+ throw new Error("simulation signer must be a valid non-zero EVM address");
26
+ }
27
+ return getAddress(candidate);
28
+ };
29
+
30
+ export const resolveSimulationSignerAddress = (options: WorkflowSignerOptions): string => {
31
+ const explicitAddress = normalizedSimulationAddress(options.explicitAddress);
32
+ const taskAddress = options.useLock
33
+ ? undefined
34
+ : normalizedSimulationAddress(options.taskAddress);
35
+ if (
36
+ explicitAddress
37
+ && taskAddress
38
+ && explicitAddress.toLowerCase() !== taskAddress.toLowerCase()
39
+ ) {
40
+ throw new Error("simulation signer sources do not match");
41
+ }
42
+ const selectedAddress = explicitAddress || taskAddress;
43
+ if (!selectedAddress) {
44
+ throw new Error("Simulation requires an explicit signer address");
45
+ }
46
+ return selectedAddress;
47
+ };
48
+
49
+ export const impersonateWorkflowSimulationSigner = async (
50
+ signerAddress: string,
51
+ ): Promise<Signer> => {
52
+ if (network.name !== "hardhat" && network.name !== "zkFork") {
53
+ throw new Error("Simulation signer impersonation requires a local fork network");
54
+ }
55
+ await network.provider.request({
56
+ method: "hardhat_impersonateAccount",
57
+ params: [signerAddress],
58
+ });
59
+ await network.provider.request({
60
+ method: "hardhat_setBalance",
61
+ params: [signerAddress, SIMULATION_SIGNER_BALANCE],
62
+ });
63
+ if (network.name === "zkFork") {
64
+ return createZkSyncNodeSigner({
65
+ provider: ethers.provider as never,
66
+ address: signerAddress,
67
+ });
68
+ }
69
+ return ethers.getSigner(signerAddress);
70
+ };
71
+
72
+ export const resolveWorkflowSigner = async (
73
+ mode: WorkflowMode,
74
+ options: WorkflowSignerOptions = {},
75
+ ): Promise<Signer> => {
76
+ if (mode === "simulate") {
77
+ return impersonateWorkflowSimulationSigner(resolveSimulationSignerAddress(options));
78
+ }
79
+
80
+ const executionCredential = mode === "execute"
81
+ ? resolveWalletCredential(process.env)
82
+ : undefined;
83
+ const zkSync = (network.config as { zksync?: boolean }).zksync === true;
84
+ if (mode === "execute" && zkSync) {
85
+ if (!executionCredential) {
86
+ throw new Error("zkSync development execution requires an explicit wallet credential");
87
+ }
88
+ const baseUrl = process.env.CUSTODY_API_BASE_URL?.trim() || undefined;
89
+ if (executionCredential.kind === "custody" && !baseUrl) {
90
+ throw new Error("Custody wallet mode requires CUSTODY_API_BASE_URL");
91
+ }
92
+ const credential = executionCredential.kind === "private-key"
93
+ ? executionCredential.privateKey
94
+ : `custody:${executionCredential.secret}:${executionCredential.address}`;
95
+ const signer = createZkSyncSigner({
96
+ ethers,
97
+ credential,
98
+ provider: ethers.provider as never,
99
+ baseUrl,
100
+ }) as Signer;
101
+ assertExecutionSignerAddress(await signer.getAddress(), options.taskAddress);
102
+ return signer;
103
+ }
104
+ if (executionCredential) {
105
+ const baseUrl = process.env.CUSTODY_API_BASE_URL?.trim() || undefined;
106
+ if (executionCredential.kind === "custody" && !baseUrl) {
107
+ throw new Error("Custody wallet mode requires CUSTODY_API_BASE_URL");
108
+ }
109
+ const credential = executionCredential.kind === "private-key"
110
+ ? executionCredential.privateKey
111
+ : `custody:${executionCredential.secret}:${executionCredential.address}`;
112
+ const signer = createSigner({
113
+ ethers,
114
+ credential,
115
+ provider: ethers.provider,
116
+ baseUrl,
117
+ }) as Signer;
118
+ assertExecutionSignerAddress(await signer.getAddress(), options.taskAddress);
119
+ return signer;
120
+ }
121
+
122
+ const [signer] = await ethers.getSigners();
123
+ return signer;
124
+ };