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,1181 @@
1
+ # Full EVM workflow reference
2
+
3
+ Reference for the full EVM template and GateTool task-based deployment workflow.
4
+ Counter commands in this reference require the optional examples; projects created
5
+ with `--no-examples` provide their own business contracts and tasks.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install
11
+ ```
12
+
13
+ `npm install` runs `patch-package` and applies the bundled
14
+ `@openzeppelin/hardhat-upgrades` patch. The template retains this patch for
15
+ OpenZeppelin plugin calls. The packaged workflow plans deployment and upgrade
16
+ calls through GateTool and controlled Multicall; it does not call the patched
17
+ `deployProxy` path. The zkSync workflow does not patch
18
+ `@matterlabs/hardhat-zksync-ethers`: local fork simulation uses GateTool's
19
+ node-managed signer, while real execution uses the same private-key or custody
20
+ EIP-712 signer boundary described below.
21
+
22
+ The patch does not write `contractInfo.json`. It only changes how OpenZeppelin
23
+ deploys proxies and implementations. The workflow runtime writes the
24
+ business-facing address to a pending registry candidate after a deploy step
25
+ succeeds. `workflow:commit-contract-info` promotes verified candidates in one
26
+ atomic registry commit; CheckCode is read-only. Implementation, transaction,
27
+ CREATE2, and gate-tool evidence stays in the execution record and
28
+ `deploymentInfo.json`.
29
+
30
+ ## Hardhat And Foundry
31
+
32
+ The template supports both toolchains after `npm install`:
33
+
34
+ ```bash
35
+ npm run compile
36
+ npm run compile:forge
37
+ npm test
38
+ npm run test:forge
39
+ npm run test:all
40
+ ```
41
+
42
+ `foundry.toml` uses Solidity 0.8.28, Cancun EVM, IR compilation, and optimizer
43
+ settings aligned with `hardhat.config.ts`. Normal project initialization installs
44
+ `forge-std` v1.16.2 into `lib/forge-std` without creating a Git submodule. If dependency
45
+ installation was skipped with `--no-install`, run `npm run install:foundry`.
46
+
47
+ Compiler, contract, and build dependencies use exact versions. The published
48
+ scaffold baseline uses `gate-evm-tools` `^1.0.28`, the minimum runtime for this template. Normal project initialization
49
+ installs that release range from the registry. When validating unreleased
50
+ GateTool changes in a local integration, override it with the locally packed
51
+ artifact inside the initialized test project:
52
+
53
+ ```bash
54
+ npm install --save-dev /absolute/path/to/gate-evm-tools-local.tgz
55
+ ```
56
+
57
+ Keep this override and its lockfile change only in the initialized local test
58
+ project; do not put a machine-specific tarball path in the reusable template.
59
+ Keep the lockfile generated by the selected package manager so each initialized
60
+ project remains reproducible. The bundled contracts and Foundry tests pin
61
+ `pragma solidity 0.8.28`.
62
+
63
+ When running this CLI's Project Docs commands on Windows, set
64
+ `GATE_PROJECT_DOCS_GIT_EXECUTABLE` to the verified absolute path of the regular
65
+ Git for Windows `git.exe` file. Project Docs does not search the project or
66
+ `PATH` for that executable.
67
+
68
+ EVM and zkSync deployments share the same manifest and Solidity sources, but
69
+ they never share compiler output. `hardhat.config.ts` reads the selected
70
+ network configuration: a target with `zksync: true` writes zksolc output to
71
+ `artifacts-zk` and `cache-zk`; every EVM target continues to use `artifacts`
72
+ and `cache`. Always compile or run with the intended `--network` before
73
+ deriving CREATE2 hashes so an EVM artifact cannot be mistaken for an EraVM
74
+ artifact (or vice versa).
75
+
76
+ ## Wallet Credential
77
+
78
+ The project uses one wallet credential for both native private keys and custody
79
+ wallets. Keep it only in the untracked project `.env` or process environment:
80
+
81
+ ```dotenv
82
+ # A normal private key remains supported without script changes.
83
+ PRIVATE_KEY=0x...
84
+
85
+ # Or use the pseudo-private-key form copied from the custody service.
86
+ PRIVATE_KEY=custody:<ProjectSecret>:<WalletAddress>
87
+ CUSTODY_API_BASE_URL=https://custody.example.com
88
+ ```
89
+
90
+ `CUSTODY_API_BASE_URL` must be an HTTP(S) base URL without embedded
91
+ credentials, query parameters, or fragments.
92
+
93
+ `WALLET_CREDENTIAL` is an optional alias for `PRIVATE_KEY`. If both variables
94
+ are configured, they must contain the same value. `hardhat.config.ts` loads the
95
+ custody plugin after the ethers and OpenZeppelin plugins. A real private key is
96
+ passed through native `networks.accounts`; a custody credential leaves native
97
+ accounts empty and supplies the remote signer through Hardhat and the workflow
98
+ signer factory. Existing deploy scripts that use `ethers.getSigners()`, contract
99
+ factories, or `upgrades.deployProxy()` therefore do not need custody-specific
100
+ branches. The bundled OpenZeppelin patch remains required for its independent
101
+ CREATE2, Multicall, and proxy deployment behavior.
102
+
103
+ SmartFlow derives the public signer address from the selected `.env` credential
104
+ when it creates a task and writes that public address to
105
+ `task.yaml.deploymentSignerAddress`. That task value is a frozen expected
106
+ identity for simulation, audit, and execution locking; it is not a second
107
+ secret or a dynamically selected account. Execute restores the signer from the
108
+ current `.env` credential and rejects it before broadcast unless its address
109
+ matches the frozen `deploymentSignerAddress`. Project Secret and pseudo-private
110
+ key values must never be written to task YAML, result evidence, logs, or Git.
111
+
112
+ zkSync planning uses only a public operator address and does not read a wallet
113
+ credential. zkSync operator execution supports either a local private-key wallet
114
+ or the configured custody wallet. Both paths use the same `zksync-ethers` EIP-712
115
+ envelope, including the locked `factoryDeps`, gas-per-pubdata, and paymaster data.
116
+ An unrelated external Admin route still fails closed before signing.
117
+
118
+ ## Workflow Model
119
+
120
+ SmartFlow should create real deployment tasks under `scripts/tasks/<taskId>/`.
121
+ This template only ships an example task at `scripts/tasks/_examples/counter-rollout`.
122
+
123
+ SmartFlow's developer lane selects one `developmentNetwork` and generates:
124
+
125
+ - `manifest.yaml`
126
+ - `parameters.schema.json`
127
+ - `parameters.yaml`
128
+ - `release.json`
129
+ - optional task-local runnable scripts only for `kind: custom`
130
+ - `docs/developer-handoff.md`
131
+
132
+ The development deploy lane executes the complete manifest on that network in
133
+ one process, verifies the business `view`/`check` suffix with the same execution
134
+ ID, and commits the verified candidate before CheckCode. Release verification
135
+ then adds `releaseTargetNetworks`, derives each target's parameters, and runs one
136
+ complete fork simulation per target. The administrator selects only a merged,
137
+ release-qualified task and creates an immutable `parameters.lock.json` plus a
138
+ per-transaction authority plan during final simulation. Execute must reuse that
139
+ exact lock and plan.
140
+
141
+ Every standard CREATE2 deployment, UUPS initial deployment, and UUPS upgrade is
142
+ prepared in-process through `prepareWorkflow(hre, request)` from
143
+ `gate-evm-tools/workflow`. GateTool owns strict artifact loading, OpenZeppelin
144
+ validation, deterministic addresses, Factory and `upgradeToAndCall` calldata,
145
+ and zkSync dependency collection. The template owns target policy, authority,
146
+ controlled Multicall wrapping, immutable plan hashing, signing, broadcasting,
147
+ receipt reconciliation, and registry writes. SmartFlow independently verifies
148
+ those canonical artifacts instead of rebuilding CREATE2 or upgrade calldata.
149
+
150
+ Development uses one protocol-aware current-state wrapper. At startup it must
151
+ **capture current latest once**, binding `chainId`, `blockNumber`, and
152
+ `blockHash` for that run only. EVM resets Hardhat 2.26.3 to that exact snapshot.
153
+ The real-network source process has no wallet accounts: it clears inherited
154
+ wallet credentials, and its tokenized loopback proxy accepts only an audited
155
+ allowlist of read-only fork RPC methods. Signing, submission, mining, and
156
+ unknown RPC methods are rejected before they reach the target provider.
157
+ For zkSync the wrapper also reads the captured target block's `protocolVersion`
158
+ and `l1BatchNumber`, then queries the installed runner capability. The bundled
159
+ anvil-zksync runner capability owns the exact runner identity and supported
160
+ protocol matrix; documentation and callers do not duplicate that matrix. The
161
+ canonical snapshot and evidence retain the real source `protocolVersion`, exact
162
+ runner identity, and the capability-resolved `runnerProtocolVersion`; a verified
163
+ compatibility mapping may make the two protocol values differ. If the installed
164
+ capability does not support the captured protocol, or the runner cannot execute
165
+ it, simulation stops before credentials, signing, or broadcast. Upgrade the
166
+ local runner or workflow dependency, then start a new simulation run.
167
+ An EVM Hardhat fork is never accepted as zkSync evidence. Every zkSync
168
+ transaction carries its explicit scheme and `factoryDeps` in the immutable
169
+ locked execution plan. A
170
+ finalized UUPS deploy or upgrade is incomplete until its `gateToolSync`
171
+ evidence confirms the stage-routed manifest update.
172
+
173
+ ## Run The Example
174
+
175
+ The example task is a workflow shape reference. Infrastructure addresses are project config:
176
+ runtime deployment, simulation, and execute-time locking read the CREATE2
177
+ factory, blank UUPS placeholder implementation, and controlled multicall from
178
+ the selected target in `config.yaml`.
179
+ SmartFlow does not ship an infrastructure address registry.
180
+ Before running against a target, configure that target's deployment
181
+ infrastructure in `config.yaml`:
182
+
183
+ ```yaml
184
+ gtDev:
185
+ environment: development
186
+ admin: ""
187
+ create2:
188
+ factory: "0x2370B48f20FFd75A46B14A9888B3E79677eFC28c"
189
+ leadingZeroBytes: 4
190
+ caller: "0x0000000000000000000000000000000000000000"
191
+ uups:
192
+ placeholderImplementation: "0x000000009F21E08bE874b78F40A6d038587E0C54"
193
+ multicall:
194
+ controlledMulticall: "0x00000000bD2f006A24b6d99baaD1323D5809948f"
195
+
196
+ zkDev:
197
+ environment: development
198
+ admin: ""
199
+ create2:
200
+ scheme: zksync-eravm
201
+ factory: "0x8Cb318b70b93cEC7E9601Fd3D391Fa28892f6D1e"
202
+ leadingZeroBytes: 4
203
+ caller: "0x0000000000000000000000000000000000000000"
204
+ uups:
205
+ placeholderImplementation: "0x00000000258e0D79F9FE344BADA1bb3c14A11dE1"
206
+ multicall:
207
+ controlledMulticall: "0x00000000ceAA9C77a78aFb970B85DB5917B05908"
208
+
209
+ zkProd:
210
+ environment: production
211
+ admin: ""
212
+ create2:
213
+ scheme: zksync-eravm
214
+ factory: "0x98fe320B225305cA57F83c322d919D477c9f1641"
215
+ leadingZeroBytes: 4
216
+ caller: "0x0000000000000000000000000000000000000000"
217
+ uups:
218
+ placeholderImplementation: "0x00000000258e0D79F9FE344BADA1bb3c14A11dE1"
219
+ multicall:
220
+ controlledMulticall: "0x00000000ceAA9C77a78aFb970B85DB5917B05908"
221
+ ```
222
+
223
+ ```bash
224
+ npm run workflow:example
225
+ ```
226
+
227
+ For a SmartFlow-generated task, development simulation creates the immutable
228
+ execution plan without creating `parameters.lock.json`:
229
+
230
+ ```bash
231
+ npm run workflow -- \
232
+ --task 20260608-counter-rollout \
233
+ --network hardhat \
234
+ --mode simulate \
235
+ --target gtDev \
236
+ --releaseKind development \
237
+ --executionId development-gtDev-1
238
+ ```
239
+
240
+ For zkSync development, use the same wrapper entry. It captures the target
241
+ block once and selects the approved EraVM runner from that block's protocol
242
+ version:
243
+
244
+ ```bash
245
+ npm run workflow -- \
246
+ --task 20260608-counter-rollout \
247
+ --network hardhat \
248
+ --mode simulate \
249
+ --target zkDev \
250
+ --releaseKind development \
251
+ --executionId development-zkDev-1 \
252
+ --simulationSigner <operator-address>
253
+ ```
254
+
255
+ The bundled runner capability resolves the pinned anvil-zksync identity and
256
+ `runnerProtocolVersion` for the captured source protocol. The runner receives
257
+ that capability-resolved value, while canonical evidence records both the real
258
+ source value and the runner value; a verified compatibility mapping may make
259
+ them differ. Documentation and callers do not duplicate the capability's
260
+ numeric protocol matrix.
261
+ The explicitly configured `127.0.0.1` `zkFork` uses GateTool's node-managed
262
+ signer after the workflow asks the local runner to impersonate the simulation
263
+ address. That signer submits the complete EraVM RPC envelope, including a
264
+ non-zero gas-per-pubdata value and `factoryDeps`, without patching third-party
265
+ dependencies or enabling impersonation on a real network. If the installed
266
+ capability does not declare the captured protocol, upgrade the runner or
267
+ workflow dependency and start a new simulation. The wrapper never changes modes
268
+ or connects a planning signer to the real target.
269
+ A reorg, hash mismatch,
270
+ or protocol metadata mismatch also fails closed and requires a new execution ID
271
+ and newly captured current snapshot. After a successful canonical simulation,
272
+ development execute must reuse its execution ID and an explicitly configured
273
+ local `PRIVATE_KEY` whose address matches the locked operator:
274
+
275
+ ```bash
276
+ npm run workflow -- \
277
+ --task 20260608-counter-rollout \
278
+ --network zkDev \
279
+ --mode execute \
280
+ --releaseKind development \
281
+ --executionId development-zkDev-1
282
+ ```
283
+
284
+ `npm run workflow` is a TypeScript wrapper around `hardhat run`; it forwards
285
+ `--network` to Hardhat and passes workflow arguments such as `--task`, `--mode`,
286
+ `--target`, `--step`, `--from`, `--simulationSigner`, and `--operator` to the runtime.
287
+ For `--mode execute` on real configured networks, the runtime fails early when
288
+ neither `WALLET_CREDENTIAL` nor `PRIVATE_KEY` is present in the project `.env`
289
+ or process environment.
290
+ Every target whose `environment` is `production` additionally requires
291
+ `--useLock`; a production execute without the immutable final-simulation plan
292
+ is rejected before credential selection, recorder creation, or broadcasting.
293
+
294
+ Development and Admin `--useLock` simulation each run as one selected public EVM
295
+ address. A normal development simulation may read `deploymentSignerAddress`
296
+ from the task's `task.yaml`; an explicit `--simulationSigner` must match it. An
297
+ Admin final simulation using `--useLock` never falls back to task metadata and
298
+ requires the argument explicitly. Both modes ignore `simulation-callers.yaml`.
299
+ No private key is required to impersonate a public address on the selected local
300
+ Hardhat or EraVM fork.
301
+
302
+ The first real execution is limited to the task's development network. It must
303
+ reuse the simulation execution ID and must not use `--useLock`:
304
+
305
+ ```bash
306
+ npm run workflow -- \
307
+ --task 20260608-counter-rollout \
308
+ --network gtDev \
309
+ --mode execute \
310
+ --releaseKind development \
311
+ --executionId development-gtDev-1
312
+ ```
313
+
314
+ Run the business verification suffix with that same execution ID, then commit
315
+ the verified development candidate before CheckCode:
316
+
317
+ ```bash
318
+ npm run workflow -- \
319
+ --task 20260608-counter-rollout \
320
+ --network gtDev \
321
+ --mode verify \
322
+ --executionId development-gtDev-1 \
323
+ --from <first-view-or-check-step>
324
+
325
+ npm run workflow:commit-contract-info -- \
326
+ --task 20260608-counter-rollout \
327
+ --commitId development-gtDev-1 \
328
+ --selection gtDev=development-gtDev-1
329
+ ```
330
+
331
+ After development verify, commit the development registry and run CheckCode
332
+ against the formal registry. The live `ReleaseSimulationCallersInput` node then
333
+ creates `scripts/tasks/<deployment-id>/simulation-callers.yaml`, after the
334
+ release target set and parameters are known and immediately before target
335
+ qualification. It contains one required default caller per target and optional
336
+ per-Manifest-step overrides; it contains public addresses only.
337
+
338
+ Each full release target qualification runs without a release-target simulation signer
339
+ argument and automatically loads that file. It must execute the complete
340
+ Manifest in order, on one shared fork per target:
341
+
342
+ ```bash
343
+ npm run workflow -- \
344
+ --task 20260608-counter-rollout \
345
+ --network hardhat \
346
+ --mode simulate \
347
+ --target gtProd \
348
+ --executionId qualification-gtProd-1
349
+ ```
350
+
351
+ There is no `--simulationSigner` compatibility fallback for release-target
352
+ qualification. Development simulation and the existing Admin workflow ignore
353
+ `simulation-callers.yaml` and retain their signer, lock, plan, and calldata
354
+ behavior.
355
+
356
+ After qualification, the Admin final simulation still writes and consumes the
357
+ immutable execution lock, so provide its operator, execution ID, source
358
+ SuperTask, and merged commit:
359
+
360
+ ```bash
361
+ npm run workflow -- \
362
+ --task 20260608-counter-rollout \
363
+ --network hardhat \
364
+ --mode simulate \
365
+ --target gtProd \
366
+ --simulationSigner <operator-address> \
367
+ --releaseKind admin_release \
368
+ --useLock \
369
+ --executionId release-gtProd-1 \
370
+ --sourceSuperTaskId <supertask-id> \
371
+ --mergeCommit <40-char-commit>
372
+ ```
373
+
374
+ EVM simulation mode uses the selected target's configured provider only in a
375
+ loopback source process. That process captures `latest` exactly once and resets
376
+ Hardhat 2.26.3 to the captured block. The workflow then exclusively claims
377
+ `results/<target>/<executionId>/simulation/` before config, manifest, or step
378
+ preflight. It immediately creates `execution.json`, `view.json`, and
379
+ `verification.json` in that directory with empty `steps`, so an early failure
380
+ cannot expose evidence from an older run. Target and execution ID are validated
381
+ as individual safe path segments; dots inside one segment cannot alias another
382
+ target or execution.
383
+
384
+ Before running the manifest, the runtime checks Factory, Controlled Multicall,
385
+ and Placeholder code at the captured block. An existing or old UUPS upgrade also
386
+ checks the proxy code, ERC-1967 implementation slot, and old implementation code
387
+ at that same block. Post-deployment assertions continue to read local `latest`
388
+ because newly deployed code is not present in the source snapshot.
389
+
390
+ Every successful simulation appends a terminal
391
+ `workflow-simulation-completed` step with the exact ordered step IDs that ran,
392
+ the applicable signer/caller binding, the immutable execution plan hash, and a
393
+ sanitized `fork` object containing only `sourceNetwork`, `chainId`, `blockNumber`,
394
+ `blockHash`, and runner kind/version
395
+ to `results/<target>/<executionId>/simulation/execution.json`. There is no
396
+ mutable latest result file. The claimed `(target, executionId, mode)` namespace
397
+ cannot be reused or overwritten, whether the run succeeds or fails; retries must
398
+ use a new execution ID. Distinct execution IDs therefore write independent files.
399
+
400
+ Immediately before terminal success, the wrapper checks the source and local
401
+ fork block hash again. A reorg or hash mismatch must fail closed; retry with a
402
+ new execution ID so the next process captures its then-current `latest`. Fork
403
+ evidence must never include an RPC URL, credential, loopback proxy URL, process
404
+ arguments, or command line.
405
+
406
+ `status.json` records the successful simulation's confined relative path as
407
+ `simulationResult`. Release Verify must copy the exact returned status evidence
408
+ path into `release.json` under the target's `simulationResult`; it must not derive
409
+ or rename the path. A failed current run clears any older top-level
410
+ `simulationResult` from global status. Admin simulation with `--useLock` records
411
+ the same scoped path in `parameters.lock.json.finalSimulation.result`, with the
412
+ lock-success update as the final fallible side effect. Failed or partial
413
+ simulations retain their scoped partial evidence but do not append the terminal
414
+ marker and cannot make a lock executable. Simulation never writes `contractInfo.json`.
415
+
416
+ The shared execution-scoped naming scheme is
417
+ `results/<target>/<executionId>/<mode>/<result>.json`, where simulate uses the
418
+ `simulation` mode directory. Separate mode claims allow Admin simulation,
419
+ execute, and verify to reuse one locked `executionId` without sharing result
420
+ files. Examples include `results/gtProd/release-gtProd-1/execute/execution.json`
421
+ and `results/gtProd/release-gtProd-1/verify/verification.json`.
422
+ A normal development simulation does not write `parameters.lock.json`; the final
423
+ release simulation shown above deliberately creates and marks the immutable lock
424
+ as simulated while retaining its release fingerprint evidence.
425
+ The lock binds `operator`, `target.signer`, and terminal simulation
426
+ `signerAddress` to the same identity. Final simulation resolves authority for
427
+ every state-changing transaction. It executes an operator route with the
428
+ selected signer and impersonates only that transaction's required external
429
+ executor on the fork. A development plan rejects every external route. An Admin
430
+ plan may interleave contiguous operator and external segments in manifest order;
431
+ the immutable transaction order and executor of every route remain fixed.
432
+
433
+ The administrator executes the locked plan with the same `executionId`:
434
+
435
+ ```bash
436
+ npm run workflow -- --task 20260608-counter-rollout --network gtProd --mode execute --useLock --executionId release-gtProd-1
437
+ ```
438
+
439
+ Execute replays the completed plan prefix without rebroadcasting it, sends the
440
+ next contiguous operator segment, and stops at the following external segment.
441
+ It cumulatively appends operator receipts and external segments to the canonical
442
+ `calldata/<network>/<executionId>/external-execution.json` package, leaving the
443
+ record in `waiting_external`. It never emits the old per-step or batch format.
444
+ After the external executor completes the current segment, reconcile finalized
445
+ chain state in bounded batches:
446
+
447
+ ```bash
448
+ npm run workflow:reconcile-external -- --task 20260608-counter-rollout --network gtProd --executionId release-gtProd-1
449
+ ```
450
+
451
+ Repeat reconciliation while it reports `waiting_external` or
452
+ `waiting_finality`. When it reports `waiting_operator`, rerun the same locked
453
+ execute command to advance the next operator segment, then reconcile again.
454
+ Only `not_required` or `reconciled` permits business verify.
455
+ SmartFlow's Admin confirmation action only records the human confirmation and
456
+ advances the workflow. The following deterministic network runner performs
457
+ reconciliation and then the manifest's read-only `view`/`check` suffix for each
458
+ network, with bounded concurrency across networks. It cannot force completion
459
+ or bypass a reverted, missing, unfinalized, or reorged transaction. A release
460
+ may contain multiple transactions, so verification is bound to the execution ID
461
+ rather than one transaction hash.
462
+
463
+ ```bash
464
+ npm run workflow -- --task 20260608-counter-rollout --network gtProd --mode verify --executionId <same-executionId> --useLock --from <first-view-or-check-step>
465
+ ```
466
+
467
+ `<same-executionId>` is the immutable lock ID used by final simulation and
468
+ execute. Verify uses its locked resolved parameters and the same pending
469
+ candidate addresses. A successful view/check verification updates
470
+ `verifyStatus` without changing the network's deployment status. After every
471
+ selected network is reconciled and verified, commit all selections atomically:
472
+
473
+ ```bash
474
+ npm run workflow:commit-contract-info -- \
475
+ --task 20260608-counter-rollout \
476
+ --commitId admin-release-1 \
477
+ --selection gtProd=<same-executionId>
478
+ ```
479
+
480
+ The commit writes `deployed_pending_code_audit` before CheckCode. SmartFlow runs
481
+ this commit automatically after its Admin verify node; there is no independent
482
+ registry-write approval button.
483
+
484
+ ## CheckCode
485
+
486
+ CheckCode is a signer-free project operation. It compiles the current sources,
487
+ checks the formal `contractInfo.json` with gate-tool, reads proxy classification
488
+ from `deploymentInfo.json`, and conditionally syncs only stale UUPS target
489
+ manifests. It never reads, promotes, or writes a registry candidate.
490
+
491
+ For a SmartFlow SuperTask, create immutable discovery evidence before the
492
+ runner starts:
493
+
494
+ ```bash
495
+ npm run workflow:checkcode-plan -- \
496
+ --runId <checkcode-run-id> \
497
+ --artifactHash <release-artifact-hash> \
498
+ --deploymentId <deployment-id> \
499
+ --sourceSuperTaskId <supertask-id> \
500
+ --developmentNetwork <development-network> \
501
+ --executionId <registry-execution-id> \
502
+ --manifestDir <configured-manifest-dir> \
503
+ --contract <saveAs-or-contract>
504
+ ```
505
+
506
+ The four SuperTask identity arguments are all-or-nothing, and the plan may
507
+ target only `developmentNetwork`. This writes the canonical plan to
508
+ `scripts/tasks/<deployment-id>/docs/checkcode-plan.md`; do not hand-edit it.
509
+
510
+ ```bash
511
+ npm run workflow:checkcode -- \
512
+ --runId <checkcode-run-id> \
513
+ --artifactHash <release-artifact-hash> \
514
+ --network gtDev \
515
+ --contract Counter
516
+ ```
517
+
518
+ Repeat `--network <network>` or `--contract <saveAs-or-contract>` to narrow the
519
+ scope. `--runId <id>` selects the report directory under
520
+ `scripts/checkcode/runs/<id>/`; otherwise the runner creates one. The same entry
521
+ is available through `npm run workflow -- --checkcode ...`. The canonical report
522
+ is `version: 1`; each entry records `manifestDir`, before/after hashes, and one of
523
+ `not_required`, `already_current`, `synced`, `proxy_kind_unknown`, or `failed`.
524
+ CheckCode does not read `PRIVATE_KEY` and is independent of a single deployment
525
+ transaction hash. CheckCode proves runtime bytecode and proxy implementation
526
+ consistency. A business check in the task manifest separately proves
527
+ initialization, ownership, roles, limits, and other configured state; neither
528
+ result substitutes for the other.
529
+
530
+ After the selected canonical report succeeds, finalize a development task with:
531
+
532
+ ```bash
533
+ npm run workflow:checkcode-finalize -- \
534
+ --deploymentId <deployment-id> \
535
+ --sourceSuperTaskId <supertask-id> \
536
+ --developmentNetwork <development-network> \
537
+ --executionId <registry-execution-id> \
538
+ --runId <checkcode-run-id>
539
+ ```
540
+
541
+ Finalize validates the report and current task identity before updating
542
+ `status.json`, `handoff.json`, and `docs/checkcode-report.md`. It keeps
543
+ `releaseTargetNetworks` empty during development; Admin Verify selects release
544
+ targets later. The formal `contractInfo.json` is byte-for-byte read-only during
545
+ CheckCode.
546
+
547
+ ## Developer Static Validation
548
+
549
+ Generate the Developer gate evidence with the template runtime instead of
550
+ assembling the report manually:
551
+
552
+ ```bash
553
+ npm run workflow:static-validate -- --task <deployment-id>
554
+ ```
555
+
556
+ The command runs `npm run compile`, `npx tsc --noEmit`, the project test command,
557
+ and parses every YAML/JSON document in the task directory. It writes
558
+ `scripts/tasks/<deployment-id>/docs/static-validation.md` and reports `failed`
559
+ if any required check fails.
560
+
561
+ Workflow subprocesses prefer the checked-out project's executable under
562
+ `node_modules/.bin`; when it is absent they use `npx --no-install`, so task runs
563
+ never install a different Hardhat, ts-node, or gate-tool version implicitly.
564
+ During execute, the signer restored from the selected wallet credential must
565
+ match the optional `task.yaml.deploymentSignerAddress` before any workflow step
566
+ or broadcast runs.
567
+
568
+ ## Release Verification Finalize
569
+
570
+ After every selected release target has complete parameters and successful
571
+ canonical simulation evidence, finalize the Verifier handoff with one runtime
572
+ command:
573
+
574
+ ```bash
575
+ npm run workflow:release-finalize -- \
576
+ --task <deployment-id> \
577
+ --network <release-target-network>
578
+ ```
579
+
580
+ Repeat `--network` for every release target. The command requires the exact
581
+ target set from `task.yaml`, `release.json`, and `simulation-callers.yaml`. It
582
+ re-reads the exact Manifest bytes, recomputes each caller network hash, and
583
+ validates the ordered terminal caller map plus every step annotation across the
584
+ execution, view, and verification results. Old signer-only target evidence has
585
+ no compatibility fallback and is stale. Only after all targets pass does it
586
+ write canonical release-ready state to
587
+ `release.json`, `status.json`, `handoff.json`, and
588
+ `docs/release-verification.md`. If any target is invalid, those formal artifacts
589
+ remain unchanged. This step does not create an Admin parameter lock, deploy to a
590
+ release network, or modify `contractInfo.json`.
591
+
592
+ For each selected target, CheckCode resolves one exact OpenZeppelin manifest
593
+ file from the configured `manifestDir` and the RPC chain ID. It never combines
594
+ proxy, implementation, or storage-layout evidence from sibling JSON files. The
595
+ canonical report records that relative file as `manifestFile`.
596
+
597
+ SmartFlow may select multiple simulation target networks, but it should call the
598
+ runtime once per target. If a simulation fails, `status.json` includes
599
+ `errorType` and `retryable`. Retry only when `retryable: true`, which is reserved
600
+ for transient RPC or network failures. Do not retry deterministic failures such
601
+ as `check_failed`, `parameter_error`, `config_error`, `contract_error`, or
602
+ `execution_reverted`; those should be sent back to the developer worktree for a
603
+ script or parameter fix.
604
+
605
+ ## Import Legacy Deployment State
606
+
607
+ Use `workflow:import-state` after migrating legacy contracts, artifacts, and the
608
+ two OpenZeppelin state directories. It builds canonical `contractInfo.json` and
609
+ `deploymentInfo.json` records from a reviewed plan and writes immutable evidence
610
+ under `scripts/migrations/<migrationId>/`.
611
+
612
+ Development and production are release stages, not different chains. For
613
+ example, `bscDev` and `bscProd` may use the same chainId (`56`), the same mainnet
614
+ chain, and the same RPC route while identifying two independent contract address
615
+ sets. Confirm them separately: `bscDev` uses `.openzeppelin.dev`, while
616
+ `bscProd` uses `.openzeppelin`. Never merge those manifests or infer the stage
617
+ from the chain ID.
618
+
619
+ Create a project-local plan such as
620
+ `scripts/migrations/legacy-bsc-state.plan.json`:
621
+
622
+ ```json
623
+ {
624
+ "version": 1,
625
+ "migrationId": "legacy-bsc-state",
626
+ "sourceProject": "legacy-vault",
627
+ "networks": {
628
+ "bscDev": {
629
+ "sourceNetwork": "development",
630
+ "releaseStage": "development",
631
+ "chainId": 56,
632
+ "manifestDir": ".openzeppelin.dev",
633
+ "contracts": [
634
+ {
635
+ "instanceId": "vault",
636
+ "contractInfoKey": "vault:Vault",
637
+ "address": "0x1111111111111111111111111111111111111111",
638
+ "actualContract": "Vault",
639
+ "proxyKind": "uups",
640
+ "implementationAddress": "0x2222222222222222222222222222222222222222"
641
+ }
642
+ ]
643
+ },
644
+ "bscProd": {
645
+ "sourceNetwork": "production",
646
+ "releaseStage": "production",
647
+ "chainId": 56,
648
+ "manifestDir": ".openzeppelin",
649
+ "contracts": [
650
+ {
651
+ "instanceId": "vault",
652
+ "contractInfoKey": "vault:Vault",
653
+ "address": "0x3333333333333333333333333333333333333333",
654
+ "actualContract": "Vault",
655
+ "proxyKind": "uups",
656
+ "implementationAddress": "0x4444444444444444444444444444444444444444"
657
+ }
658
+ ]
659
+ }
660
+ }
661
+ }
662
+ ```
663
+
664
+ First print the plan-bound confirmation tokens. Review the network, release
665
+ stage, manifest directory, proxy address, implementation address, and chain ID
666
+ before copying each token:
667
+
668
+ ```bash
669
+ npm run workflow:import-state -- \
670
+ --plan scripts/migrations/legacy-bsc-state.plan.json \
671
+ --print-confirmations
672
+ ```
673
+
674
+ Then provide every token independently:
675
+
676
+ ```bash
677
+ npm run workflow:import-state -- \
678
+ --plan scripts/migrations/legacy-bsc-state.plan.json \
679
+ --confirm 'migration-v1:legacy-bsc-state:bscDev:development:.openzeppelin.dev:<plan-bound-hash>' \
680
+ --confirm 'migration-v1:legacy-bsc-state:bscProd:production:.openzeppelin:<plan-bound-hash>'
681
+ ```
682
+
683
+ The importer verifies target configuration, chain ID, deployed code, artifact,
684
+ ERC-1967 proxy kind and implementation, then runs gate-tool bytecode checking
685
+ before committing any formal state. A zero gate-tool exit is insufficient by
686
+ itself: the bytecode report must exist as a regular file, contain valid JSON,
687
+ and retain the hash recorded in the evidence.
688
+
689
+ Every output is durably staged before a transaction journal is written.
690
+ `contractInfo.json`, `deploymentInfo.json`, and the bytecode report are renamed
691
+ first; immutable `state-import.json` evidence is renamed last as the commit
692
+ marker. Its `integrityHash` binds the complete evidence document. On the next
693
+ run, crash recovery reads the journal and either restores every exact pre-import
694
+ byte stream or confirms the fully committed hashes before deleting staged
695
+ files. Retrying the same completed migration is therefore idempotent, while a
696
+ missing/tampered report, evidence field, symlinked path component, or mixed
697
+ formal state fails closed.
698
+
699
+ This is a signer-free, non-broadcast migration operation. Confirmation printing
700
+ finishes before Hardhat loads; an actual import sets `GATE_MIGRATION_READ_ONLY`
701
+ so Hardhat config exposes no signer accounts. It never reads a private key and
702
+ must not broadcast a transaction to mainnet. Acceptance uses
703
+ compiler/tests, this import audit, `workflow:checkcode`, and dry-run or fork
704
+ simulation for legacy script entrypoints. A real mainnet transaction is never an
705
+ acceptance requirement.
706
+
707
+ ## Configuration
708
+
709
+ `hardhat.config.ts` owns RPC route selection, public fallbacks, chain ids, and
710
+ signer setup. The tracked `rpc.env` file provides the shared `BASE_RPC_URI` for
711
+ the project; SmartFlow may populate its initially empty value once when it
712
+ creates a new internal project. `.env` remains untracked and only provides
713
+ `WALLET_CREDENTIAL`/`PRIVATE_KEY`, `CUSTODY_API_BASE_URL`, and the optional full
714
+ `ZKSYNC_RPC_URL`.
715
+
716
+ Each remote network declares `route`, `publicFallback`, and `useBaseRpc`
717
+ explicitly. When `useBaseRpc` is `true` and `BASE_RPC_URI` is non-empty, the
718
+ resolved URL is `<BASE_RPC_URI>/<route>/` with exactly one separator and a
719
+ trailing slash. Otherwise Hardhat uses that network's public fallback. A
720
+ `BASE_RPC_URI` already present in the process environment overrides
721
+ `rpc.env`.
722
+
723
+ The internal Base RPC routes enabled by the template are `eth`, `bsc`,
724
+ `optimism`, `arbitrum`, `base`, `avaxc`, `blast`, `polygon`,
725
+ `world`, `gatelayer`, `eni`, `bera`, `sonic`, and `linea`. Networks without an
726
+ internal route, such as Fantom and Sepolia, explicitly disable Base RPC and
727
+ always use their public fallback.
728
+
729
+ zkSync capture must call `zks_getBlockDetails`, so `zkDev` and `zkProd` do not
730
+ inherit `BASE_RPC_URI`. They use `ZKSYNC_RPC_URL` when set, otherwise the full
731
+ official `https://mainnet.era.zksync.io` endpoint.
732
+
733
+ `config.yaml` owns long-lived business parameters and deployment
734
+ infrastructure addresses. Top-level keys starting with `_` are shared profiles,
735
+ not Hardhat networks; concrete network keys inherit those profiles:
736
+
737
+ ```yaml
738
+ _profiles:
739
+ create2Base: &create2Base
740
+ leadingZeroBytes: 4
741
+ caller: "0x0000000000000000000000000000000000000000"
742
+
743
+ create2Dev: &create2Dev
744
+ <<: *create2Base
745
+ factory: "0xYourDevCreate2Factory"
746
+
747
+ create2Prod: &create2Prod
748
+ <<: *create2Base
749
+ factory: "0xYourProdCreate2Factory"
750
+
751
+ zkCreate2Base: &zkCreate2Base
752
+ <<: *create2Base
753
+ scheme: zksync-eravm
754
+
755
+ zkCreate2Dev: &zkCreate2Dev
756
+ <<: *zkCreate2Base
757
+ factory: "0x8Cb318b70b93cEC7E9601Fd3D391Fa28892f6D1e"
758
+
759
+ zkCreate2Prod: &zkCreate2Prod
760
+ <<: *zkCreate2Base
761
+ factory: "0x98fe320B225305cA57F83c322d919D477c9f1641"
762
+
763
+ uups: &defaultUups
764
+ placeholderImplementation: "0xYourBlankUUPSPlaceholderImplementation"
765
+
766
+ zkUups: &zkUups
767
+ placeholderImplementation: "0x00000000258e0D79F9FE344BADA1bb3c14A11dE1"
768
+
769
+ multicall: &defaultMulticall
770
+ controlledMulticall: "0xYourControlledMulticall"
771
+
772
+ zkMulticall: &zkMulticall
773
+ controlledMulticall: "0x00000000ceAA9C77a78aFb970B85DB5917B05908"
774
+
775
+ dev: &devProfile
776
+ environment: development
777
+ admin: ""
778
+ create2: *create2Dev
779
+ uups: *defaultUups
780
+ multicall: *defaultMulticall
781
+
782
+ prod: &prodProfile
783
+ environment: production
784
+ admin: "0xYourSafeOrAdminAddress"
785
+ create2: *create2Prod
786
+ uups: *defaultUups
787
+ multicall: *defaultMulticall
788
+
789
+ zkDev: &zkDevProfile
790
+ environment: development
791
+ admin: ""
792
+ create2: *zkCreate2Dev
793
+ uups: *zkUups
794
+ multicall: *zkMulticall
795
+
796
+ zkProd: &zkProdProfile
797
+ environment: production
798
+ admin: "0xYourSafeOrAdminAddress"
799
+ create2: *zkCreate2Prod
800
+ uups: *zkUups
801
+ multicall: *zkMulticall
802
+
803
+ ethDev:
804
+ <<: *devProfile
805
+
806
+ ethProd:
807
+ <<: *prodProfile
808
+
809
+ zkDev:
810
+ <<: *zkDevProfile
811
+
812
+ zkProd:
813
+ <<: *zkProdProfile
814
+ ```
815
+
816
+ Every selectable target has an explicit `environment` inherited from its
817
+ profile: `local`, `development`, or `production`. Consumers should classify a
818
+ parsed target from this field. The workflow does not infer the environment from
819
+ the network name, alias, RPC URL, or chain ID.
820
+
821
+ Every target also declares an explicit `openzeppelin.manifestDir`. Local tooling
822
+ uses `.openzeppelin.local`, development networks use `.openzeppelin.dev`,
823
+ Sepolia uses `.openzeppelin.sepolia`, and production networks use
824
+ `.openzeppelin`. Non-production targets must never fall back to the production
825
+ directory. The CLI exports `MANIFEST_DEFAULT_DIR` before Hardhat loads the
826
+ OpenZeppelin plugin. Multi-network CheckCode starts one isolated sync child per
827
+ target so one target cannot mutate another target's manifest.
828
+
829
+ `admin: ""` or `admin: "deployer"` resolves to the current signer. The workflow
830
+ does not use a default fallback; if `--network ethProd` is selected, `config.yaml`
831
+ must contain an `ethProd` entry.
832
+
833
+ For setup or upgrade calls, final simulation checks the contract's `owner()` or
834
+ `admin()` and controlled-multicall permissions. It records the exact operator or
835
+ external executor per transaction. Real execute enforces every locked
836
+ `to/value/data/operation/executor` tuple, advances one ordered operator segment,
837
+ and appends the following external segment without changing its executor. A
838
+ `view`/`check` step runs only after external reconciliation completes.
839
+
840
+ ## Workflow Steps
841
+
842
+ Use standard workflow steps whenever the action can be described declaratively:
843
+
844
+ - `deploy`: deploy a contract and stage its address in a pending registry candidate.
845
+ - `call`: plan and execute state-changing contract calls under per-transaction authority.
846
+ - `view`: read contract state and record the result.
847
+ - `check`: read contract state and fail when it does not match the expected value.
848
+ - `upgrade`: upgrade execution slot for proxy projects.
849
+
850
+ For `call`, `view`, and `check`, `contract` is the ABI or fully qualified
851
+ contract name. If the deployed instance is recorded under a different `saveAs`,
852
+ set `deployment` to that instance ID. The runtime resolves both an exact
853
+ contract key and a unique `<saveAs>:<actualContract>` alias:
854
+
855
+ ```yaml
856
+ - id: call-core-vault-cap
857
+ kind: call
858
+ contract: contracts/core/Vault.sol:Vault
859
+ deployment: CoreVault
860
+ calls:
861
+ - method: setCap
862
+ args:
863
+ - $param.cap
864
+ ```
865
+
866
+ Every `deploy` step must use `strategy: create2`, define a `saveAs` value, and
867
+ `saveAs` must be unique within the task. It is the deployment instance id used
868
+ by `contractInfo.json` and by network-scoped salts. It must not contain `:` because
869
+ that separator belongs to the gate-tool alias format. If `saveAs` equals the
870
+ actual Solidity contract name, the registry key is just the contract name.
871
+ Otherwise the key is `<saveAs>:<actualContract>`. Fully qualified artifact names
872
+ are reduced to their final Solidity contract name for this key.
873
+
874
+ If two Solidity contracts have the same name, use a fully qualified contract
875
+ name and different `saveAs` values:
876
+
877
+ ```yaml
878
+ - id: deploy-core-vault
879
+ kind: deploy
880
+ contract: contracts/core/Vault.sol:Vault
881
+ saveAs: CoreVault
882
+
883
+ - id: deploy-reward-vault
884
+ kind: deploy
885
+ contract: contracts/reward/Vault.sol:Vault
886
+ saveAs: RewardVault
887
+ ```
888
+
889
+ Those steps produce `CoreVault:Vault` and `RewardVault:Vault`. Later steps use
890
+ `deployment: CoreVault` or `deployment: RewardVault`; they do not need to repeat
891
+ the suffix.
892
+
893
+ CREATE2 deploys keep salt values in each network's task parameters under
894
+ `params.<network>.salts.<saveAs>`:
895
+
896
+ - A development salt is reused only when the target scheme, factory, caller salt prefix, scheme-specific hashes, and leading-zero policy still produce the recorded expected address. Otherwise SmartFlow mines a target-specific salt.
897
+ - different `saveAs` values must not share one salt value; each contract or deployment instance gets its own salt group.
898
+ - For UUPS contracts, the canonical business address is the proxy. The business task only needs a network-scoped proxy salt. Later business implementation addresses are ordinary upgrade outputs and do not use vanity salts.
899
+
900
+ SmartFlow is the CREATE2 salt source. The developer lane should use the built-in
901
+ CREATE2 resolver/miner, write the requested artifacts to
902
+ `scripts/tasks/<taskId>/create2-requests.json`, and write confirmed results to
903
+ `scripts/tasks/<taskId>/create2-results.json`. Runtime execution must only
904
+ consume the locked salt values already written to `parameters.yaml`; it must not
905
+ mine new salts, call an external salt service, or silently replace a salt during
906
+ simulation or execution.
907
+
908
+ `create2-requests.json` uses the version-2 catalog exclusively. It contains
909
+ exactly `profiles.evm.requests` and `profiles.zksync-eravm.requests`, with an
910
+ explicit `scheme` on every request. Top-level `requests`, profile-level
911
+ `targetNetworks`, the retired `resolver` and `addressParam` fields, mixed
912
+ EVM/zkSync hash fields, and salt paths under `params.global` are invalid.
913
+ SmartFlow binds the selected profile to each actual
914
+ target network at runtime. `create2-results.json` remains version 1 and every
915
+ trusted result records its explicit scheme and target network.
916
+
917
+ For non-upgradeable EVM contracts, SmartFlow mines the salt from the standard
918
+ CREATE2 inputs:
919
+
920
+ ```text
921
+ predicted = last20bytes(keccak256(0xff ++ factory ++ salt ++ initCodeHash))
922
+ initCodeHash = keccak256(contract bytecode ++ abi.encode(constructorArgs))
923
+ ```
924
+
925
+ `leadingZeroBytes: 4` means the mined address must start with
926
+ `0x00000000`. Under both schemes, `caller` is the required 20-byte salt prefix
927
+ stored in the high 20 bytes of every 32-byte salt; the remaining 12 bytes are
928
+ the mined nonce. It is not the Factory address or the deployment transaction
929
+ sender, and it enters address derivation only through the complete salt. SmartFlow supplies the scheme-specific
930
+ bytecode and constructor-input hashes, while GateTool remains the canonical
931
+ EraVM address and deployment-calldata implementation.
932
+
933
+ ```yaml
934
+ - id: deploy-counter
935
+ kind: deploy
936
+ contract: Counter
937
+ saveAs: Counter
938
+ strategy: create2
939
+ create2:
940
+ factory: $target.create2.factory
941
+ salt: $param.salts.Counter.deploySalt
942
+ expectedAddress: $param.salts.Counter.expectedAddress
943
+ leadingZeroBytes: $target.create2.leadingZeroBytes
944
+ ```
945
+
946
+ Non-upgradeable CREATE2 deployments default through the configured
947
+ `target.multicall.controlledMulticall`.
948
+ The runtime sends the factory `deploy(...)` call through
949
+ that contract instead of calling the factory directly, and any future
950
+ post-deploy calls can be included in the same batch.
951
+
952
+ Upgradeable deployments should use the pre-deployed blank `UUPSPlaceholder`
953
+ implementation as the initial UUPS implementation. Treat `UUPSPlaceholder` as
954
+ chain-level infrastructure, like the CREATE2 factory. Before generating or
955
+ executing a proxySalt, every target network must declare the exact factory and
956
+ configured placeholder implementation address it will use. The placeholder
957
+ implementation is read from `target.uups.placeholderImplementation`. The proxy
958
+ CREATE2 initCode is `ERC1967Proxy(placeholderImplementation, 0x)`; if the
959
+ factory or placeholder implementation address differs by chain, the same proxy
960
+ salt will not produce the same proxy address.
961
+
962
+ Production rollouts should pre-deploy and verify this `UUPSPlaceholder`
963
+ infrastructure on every target network before the business deployment task.
964
+ The business deployment workflow does not mine or deploy a placeholder
965
+ implementation; it consumes `target.uups.placeholderImplementation` and
966
+ only deploys the CREATE2 proxy.
967
+
968
+ For `upgradeableStrategy: uups-placeholder-proxy`, SmartFlow mines the proxy
969
+ salt from the proxy init code hash:
970
+
971
+ ```text
972
+ initCodeHash = keccak256(ERC1967Proxy bytecode ++ abi.encode(placeholderImplementation, 0x))
973
+ ```
974
+
975
+ The business implementation bytecode hash is not used for proxy salt mining.
976
+
977
+ The placeholder has no owner, admin, or business state. It only exists so the
978
+ proxy initCode is stable. The deployment workflow must run an atomic first upgrade
979
+ in the same transaction that creates the proxy. If the first upgrade
980
+ fails, the whole transaction reverts and no placeholder proxy is left behind.
981
+
982
+ The real business implementation owns its own `initialize(...)` parameters,
983
+ owner/admin setup, and future `_authorizeUpgrade` policy. Add a final ownership handoff
984
+ step after deployment-time setup to transfer control to `$target.admin`
985
+ or the production Safe.
986
+
987
+ `UUPSPlaceholder` does not touch OpenZeppelin Initializable state. The real
988
+ business implementation runs its own `initialize(...)` during the atomic first
989
+ `upgradeToAndCall` call.
990
+
991
+ Use `upgradeableStrategy: uups-placeholder-proxy` in task metadata/docs. The
992
+ `saveAs` value identifies the business proxy. The `firstUpgrade.contract` value
993
+ is the actual business contract used for the `contractInfo.json` key; the
994
+ placeholder contract is never used as that alias suffix. Implementation and
995
+ placeholder addresses are retained only in the per-execution deployment record.
996
+
997
+ ```yaml
998
+ - id: deploy-counter-placeholder-proxy
999
+ kind: deploy
1000
+ contract: CounterUUPS
1001
+ saveAs: Counter
1002
+ strategy: create2
1003
+ upgradeableStrategy: uups-placeholder-proxy
1004
+ proxy:
1005
+ kind: uups
1006
+ initializer: false
1007
+ create2:
1008
+ factory: $target.create2.factory
1009
+ salt: $param.salts.Counter.proxySalt
1010
+ leadingZeroBytes: $target.create2.leadingZeroBytes
1011
+ expectedAddress: $param.salts.Counter.proxyAddress
1012
+ firstUpgrade:
1013
+ contract: CounterUUPS
1014
+ call:
1015
+ method: initialize
1016
+ args:
1017
+ - $target.admin
1018
+ - $param.initialValue
1019
+
1020
+ - id: call-transfer-counter-owner
1021
+ kind: call
1022
+ contract: CounterUUPS
1023
+ deployment: Counter
1024
+ calls:
1025
+ - method: transferOwnership
1026
+ args:
1027
+ - $target.admin
1028
+ ```
1029
+
1030
+ Task parameters should group salts by deployment instance id:
1031
+
1032
+ ```yaml
1033
+ params:
1034
+ gtDev:
1035
+ salts:
1036
+ Counter:
1037
+ proxySalt: "0x..."
1038
+ proxyAddress: "0x00000000..."
1039
+ CoreVault:
1040
+ deploySalt: "0x..."
1041
+ RewardVault:
1042
+ deploySalt: "0x..."
1043
+ gtProd:
1044
+ salts:
1045
+ Counter:
1046
+ proxySalt: "0x..."
1047
+ proxyAddress: "0x00000000..."
1048
+ ```
1049
+
1050
+ Real and simulated proxy upgrades call the in-process GateTool workflow first.
1051
+ `prepareWorkflow(hre, request)` compiles, performs the scheme-appropriate
1052
+ OpenZeppelin implementation and storage-layout validation, and returns a
1053
+ prepare-only plan containing the implementation deployment and canonical
1054
+ `upgradeToAndCall` transaction. It never signs, broadcasts, or mutates a
1055
+ manifest. The workflow then applies its own authority policy, locks the exact
1056
+ transactions, and sends only in execute mode. On zkSync, bytecode-publishing
1057
+ transactions also lock and send the exact normalized `factoryDeps` through the
1058
+ local `zksync-ethers` wallet.
1059
+
1060
+ After a non-simulation UUPS receipt is finalized, the workflow runs GateTool
1061
+ sync against the target's configured `openzeppelin.manifestDir` and records the
1062
+ committed transaction as `gateToolSync` evidence. A failed or missing sync keeps
1063
+ the deployment or upgrade incomplete; prepare mode itself never writes the
1064
+ manifest.
1065
+
1066
+ EVM remains the default when `create2.scheme` is absent. zkSync uses the target
1067
+ block's protocol with the bundled runner capability, while canonical evidence
1068
+ retains the captured source protocol version and the capability-resolved runner
1069
+ protocol version; a verified compatibility mapping may make them differ.
1070
+ The workflow does not copy a protocol matrix: support comes only from the
1071
+ installed capability. An undeclared protocol or runner failure requires upgrading
1072
+ the runner or workflow dependency and starting a new simulation. For an approved
1073
+ protocol, the local private-key or custody operator sends the immutable
1074
+ `customData.factoryDeps`; external Admin routes still fail closed until an exact
1075
+ EIP-712 handoff transport exists. An EVM Hardhat fork must not be used as an EraVM simulation. zkSync CheckCode is supported
1076
+ through the scheme-aware target compiler and GateTool evidence path, including
1077
+ the finalized UUPS deployment record and immutable manifest-sync evidence.
1078
+
1079
+ ```yaml
1080
+ - id: upgrade-counter
1081
+ kind: upgrade
1082
+ proxy: Counter
1083
+ old: CounterUUPS
1084
+ contract: CounterUUPSV2
1085
+ proxyKind: uups
1086
+ ```
1087
+
1088
+ `custom` is the special-case escape hatch for logic that cannot be represented
1089
+ by standard steps:
1090
+
1091
+ ```yaml
1092
+ - id: custom-init
1093
+ kind: custom
1094
+ script: scripts/tasks/20260611-counter/scripts/02_custom_init.ts
1095
+ ```
1096
+
1097
+ Deployer review should treat `kind: custom` as arbitrary project code. Custom
1098
+ scripts should still reuse workflow helpers for deployment records, authority
1099
+ checks, and reports. Admin release plans reject a custom step after the external
1100
+ suffix begins.
1101
+
1102
+ ## Files
1103
+
1104
+ - `config.yaml`: long-lived business config by Hardhat network key.
1105
+ - `contractInfo.json`: current business-facing contract or proxy addresses by network key.
1106
+ - `deploymentInfo.json`: proxy kind, implementation, source record, and other deployment metadata.
1107
+ - `gate-workflow run`: packaged workflow entrypoint used by deployers.
1108
+ - `gate-evm-tools/runtime/steps/*`: packaged standard step executors for deploy, call, view, check, upgrade, and custom.
1109
+ - `gate-evm-tools/runtime/lib/*`: packaged shared workflow runtime helpers for config, parameters, CREATE2, calldata, authority, reporting, and deployment records.
1110
+ - `scripts/tasks/<taskId>/manifest.yaml`: task workflow execution plan.
1111
+ - `scripts/tasks/<taskId>/parameters.yaml`: per-network task parameters and explicitly shared business parameters.
1112
+ - `scripts/tasks/<taskId>/release.json`: source SuperTask, development network, and release-qualified network fingerprints.
1113
+ - `scripts/tasks/<taskId>/create2-requests.json`: SmartFlow built-in CREATE2 resolver requests for deploy steps.
1114
+ - `scripts/tasks/<taskId>/create2-results.json`: resolved CREATE2 salts, expected addresses, and resolver metadata.
1115
+ - `scripts/tasks/<taskId>/scripts`: optional SmartFlow-generated custom scripts.
1116
+ - `scripts/tasks/<taskId>/results/<target>/<executionId>/<mode>/<result>.json`: single-use execution, view, and verification envelopes for one workflow mode.
1117
+ - `scripts/tasks/<taskId>/results/<network>.<executionId>.deployment.json`: deploy and upgrade evidence for one execute run.
1118
+ - `scripts/tasks/<taskId>/results/<network>/<executionId>/execution-plan.json`: immutable per-transaction authority plan.
1119
+ - `scripts/tasks/<taskId>/calldata/<network>/<executionId>/external-execution.json`: canonical cumulative external segment package.
1120
+ - `scripts/tasks/<taskId>/results/<network>/<executionId>/external-reconciliation.json`: finalized chain reconciliation evidence.
1121
+ - `scripts/tasks/<taskId>/results/registry/<commitId>.json`: all-network registry commit evidence.
1122
+ - `contractInfo.pending.<executionId>.json`: stable v1 evidence locator; read its JSON `status` (`pending` or `promoted`) for the lifecycle state.
1123
+ - `scripts/checkcode/runs/<runId>`: effective registry, raw gate-tool report, sync evidence, and final CheckCode report.
1124
+
1125
+ `contractInfo.json` uses the same string-only shape as gate-tool. Values are
1126
+ always address strings; nested address or deployment objects are rejected:
1127
+
1128
+ ```json
1129
+ {
1130
+ "gtDev": {
1131
+ "Vault": "0xVaultProxy",
1132
+ "USDCVault:Vault": "0xUsdcVaultProxy",
1133
+ "USDTVault:Vault": "0xUsdtVaultProxy"
1134
+ }
1135
+ }
1136
+ ```
1137
+
1138
+ Every execute run containing a deploy or upgrade step writes
1139
+ `scripts/tasks/<taskId>/results/<network>.<executionId>.deployment.json`. The
1140
+ record starts as `prepared`, captures the complete `contractInfo.json` before
1141
+ snapshot, and records each step's instance ID, actual contract, registry key,
1142
+ factory, multicall, salt, expected and actual addresses, implementation,
1143
+ transaction hash, and CREATE2 reuse state. A successful deployment writes an
1144
+ immutable before backup plus `contractInfo.pending.<executionId>.json`, then
1145
+ waits in `waiting_code_check`. It does not change the formal registry.
1146
+ `workflow:commit-contract-info` requires finalized execution and same-execution
1147
+ business verification, promotes all selected candidates in one atomic registry
1148
+ write, updates `deploymentInfo.json`, and records `deployed_pending_code_audit`.
1149
+ CheckCode then audits the formal registry without changing it.
1150
+ Promotion retains the canonical `.pending.` file as terminal evidence because
1151
+ deployment records and recovery reports continue to reference that path. Do not
1152
+ delete, move, or rename it while those evidence references exist.
1153
+
1154
+ Upgrade records include the gate-tool output path and parsed output but do not
1155
+ rewrite `contractInfo.json`, because the business proxy address is unchanged.
1156
+ An external-admin run is marked `waiting_external`; a failed run remains
1157
+ `partial`, preserving prepared changes and the before and planned snapshots for
1158
+ recovery.
1159
+
1160
+ When a normal deployed contract already exists, the administrator must choose
1161
+ `reuse` or `redeploy`. Reuse requires passed CheckCode evidence for the same
1162
+ address and release artifact hash. Redeploy requires a new salt, a different
1163
+ expected address, and a reason; the old registry is backed up at registry commit.
1164
+ ERC1967/UUPS proxies cannot use redeploy and must continue through an upgrade
1165
+ step.
1166
+
1167
+ The runtime serializes `contractInfo.json` read-modify-write operations across
1168
+ workflow processes, so parallel network executions cannot overwrite one
1169
+ another. A concurrent candidate for the same network and deployment instance is
1170
+ rejected. Generated execution IDs include
1171
+ millisecond precision and a random suffix, and an existing deployment-record
1172
+ path is never overwritten. Locks left by a terminated workflow process are
1173
+ detected and recovered before the next registry update.
1174
+
1175
+ ### Packaged workflow preview
1176
+
1177
+ Workflow implementations are provided by `gate-evm-tools`; npm scripts invoke the packaged CLI directly; the template contains no workflow forwarding directory. Business scripts, contracts, configuration and task data stay in this project. The dependency allows `^1.0.28`; the lockfile pins the installed version. Before npm publication, validate using its local `.tgz` with `npm install --save-dev --save-exact /path/to/gate-evm-tools-1.0.28.tgz` before running commands. Keep the updated lockfile with package.json.
1178
+
1179
+ `npx --no-install gate-workflow --help` exposes compiled workflow commands without a manual ts-node preload. Existing npm commands remain supported. Before upgrading an existing task, finish it with the original runtime or reconcile it and prepare a new execution ID; execution bindings reject a different package build. `gate-workflow migrate` previews removal of recognized baseline files and shims; `--apply` backs up originals, updates known commands/imports and removes known runtime scripts; customized files or unresolved references require manual review. It does not change business data or install dependencies.
1180
+
1181
+ Network declarations live directly in `hardhat.config.ts` under its single `networks` block. Edit names, chain IDs, RPC routes/fallbacks and zkSync flags there; do not create a second network list. `createNetworkHelpers` from `gate-evm-tools/runtime-config/networks` supplies only account/RPC/fork mechanics. Add `rpcUrl: process.env.BSC_DEV_RPC_URL` to one `remoteNetwork({ ... })` entry to override its RPC, or spread that entry into `{ ...remoteNetwork({ ... }), timeout: 60000 }` for other Hardhat fields. Load rpc.env/.env before creating the helpers. Dev/Prod represent business environments, not testnet/mainnet. Compiler versions/settings remain project-owned; overlay migration merges the network block and keeps the original toolchain. The deprecated `createTemplateNetworks` export remains for older generated projects only and is not called by the current template.