gate-evm-tools 1.0.31 → 1.2.1

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 (349) hide show
  1. package/README.md +34 -20
  2. package/bin/cli.js +3 -0
  3. package/bin/delivery.cjs +8 -7
  4. package/dist/commands/check.d.ts.map +1 -1
  5. package/dist/commands/check.js +26 -2
  6. package/dist/commands/check.js.map +1 -1
  7. package/dist/commands/plan/index.d.ts.map +1 -1
  8. package/dist/commands/plan/index.js +1 -1
  9. package/dist/commands/plan/index.js.map +1 -1
  10. package/dist/core/preparation/batch.d.ts +26 -0
  11. package/dist/core/preparation/batch.d.ts.map +1 -0
  12. package/dist/core/preparation/batch.js +72 -0
  13. package/dist/core/preparation/batch.js.map +1 -0
  14. package/dist/core/preparation/evm.d.ts +23 -4
  15. package/dist/core/preparation/evm.d.ts.map +1 -1
  16. package/dist/core/preparation/evm.js +19 -3
  17. package/dist/core/preparation/evm.js.map +1 -1
  18. package/dist/core/preparation/evmManifestSync.d.ts +5 -0
  19. package/dist/core/preparation/evmManifestSync.d.ts.map +1 -1
  20. package/dist/core/preparation/evmManifestSync.js +15 -7
  21. package/dist/core/preparation/evmManifestSync.js.map +1 -1
  22. package/dist/core/preparation/index.d.ts +2 -2
  23. package/dist/core/preparation/index.d.ts.map +1 -1
  24. package/dist/core/preparation/manifest.d.ts +2 -0
  25. package/dist/core/preparation/manifest.d.ts.map +1 -1
  26. package/dist/core/preparation/manifest.js +2 -2
  27. package/dist/core/preparation/manifest.js.map +1 -1
  28. package/dist/core/preparation/normalize.d.ts.map +1 -1
  29. package/dist/core/preparation/normalize.js +53 -11
  30. package/dist/core/preparation/normalize.js.map +1 -1
  31. package/dist/core/preparation/transparent.d.ts +23 -0
  32. package/dist/core/preparation/transparent.d.ts.map +1 -0
  33. package/dist/core/preparation/transparent.js +103 -0
  34. package/dist/core/preparation/transparent.js.map +1 -0
  35. package/dist/core/preparation/types.d.ts +47 -5
  36. package/dist/core/preparation/types.d.ts.map +1 -1
  37. package/dist/core/preparation/zksync.d.ts.map +1 -1
  38. package/dist/core/preparation/zksync.js +2 -0
  39. package/dist/core/preparation/zksync.js.map +1 -1
  40. package/dist/custody/credential.d.ts.map +1 -1
  41. package/dist/custody/credential.js +1 -6
  42. package/dist/custody/credential.js.map +1 -1
  43. package/dist/deployment-evm/index.d.ts +4 -0
  44. package/dist/deployment-evm/index.d.ts.map +1 -0
  45. package/dist/deployment-evm/index.js +3 -0
  46. package/dist/deployment-evm/index.js.map +1 -0
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +4 -0
  49. package/dist/index.js.map +1 -1
  50. package/dist/sync/index.d.ts.map +1 -1
  51. package/dist/sync/index.js +5 -0
  52. package/dist/sync/index.js.map +1 -1
  53. package/dist/types.d.ts +3 -0
  54. package/dist/types.d.ts.map +1 -1
  55. package/dist/workflow/index.d.ts +4 -1
  56. package/dist/workflow/index.d.ts.map +1 -1
  57. package/dist/workflow/index.js +2 -0
  58. package/dist/workflow/index.js.map +1 -1
  59. package/dist-cjs/core/preparation/batch.js +76 -0
  60. package/dist-cjs/core/preparation/batch.js.map +1 -0
  61. package/dist-cjs/core/preparation/evm.js +25 -7
  62. package/dist-cjs/core/preparation/evm.js.map +1 -1
  63. package/dist-cjs/core/preparation/evmManifestSync.js +15 -7
  64. package/dist-cjs/core/preparation/evmManifestSync.js.map +1 -1
  65. package/dist-cjs/core/preparation/manifest.js +2 -2
  66. package/dist-cjs/core/preparation/manifest.js.map +1 -1
  67. package/dist-cjs/core/preparation/normalize.js +53 -11
  68. package/dist-cjs/core/preparation/normalize.js.map +1 -1
  69. package/dist-cjs/core/preparation/transparent.js +110 -0
  70. package/dist-cjs/core/preparation/transparent.js.map +1 -0
  71. package/dist-cjs/core/preparation/zksync.js +2 -0
  72. package/dist-cjs/core/preparation/zksync.js.map +1 -1
  73. package/dist-cjs/custody/credential.js +1 -6
  74. package/dist-cjs/custody/credential.js.map +1 -1
  75. package/dist-cjs/deployment-evm/index.js +10 -0
  76. package/dist-cjs/deployment-evm/index.js.map +1 -0
  77. package/dist-cjs/sync/index.js +5 -0
  78. package/dist-cjs/sync/index.js.map +1 -1
  79. package/dist-cjs/workflow/index.js +11 -1
  80. package/dist-cjs/workflow/index.js.map +1 -1
  81. package/dist-runtime/config/hardhatAdapters.js +2 -1
  82. package/dist-runtime/config/hardhatAdapters.js.map +1 -1
  83. package/dist-runtime/delivery/aggregate-bootstrap.js +3 -1
  84. package/dist-runtime/delivery/aggregate-bootstrap.js.map +1 -1
  85. package/dist-runtime/delivery/aggregate-channel.js +7 -3
  86. package/dist-runtime/delivery/aggregate-channel.js.map +1 -1
  87. package/dist-runtime/delivery/aggregate-diagnostics.d.ts +14 -0
  88. package/dist-runtime/delivery/aggregate-diagnostics.js +73 -0
  89. package/dist-runtime/delivery/aggregate-diagnostics.js.map +1 -0
  90. package/dist-runtime/delivery/aggregate-inputs.d.ts +13 -9
  91. package/dist-runtime/delivery/aggregate-source.js +11 -3
  92. package/dist-runtime/delivery/aggregate-source.js.map +1 -1
  93. package/dist-runtime/delivery/aggregate-worker.js +12 -4
  94. package/dist-runtime/delivery/aggregate-worker.js.map +1 -1
  95. package/dist-runtime/delivery/aggregate.js +2 -2
  96. package/dist-runtime/delivery/aggregate.js.map +1 -1
  97. package/dist-runtime/delivery/business-extension.d.ts +10 -0
  98. package/dist-runtime/delivery/business-extension.js +38 -0
  99. package/dist-runtime/delivery/business-extension.js.map +1 -0
  100. package/dist-runtime/delivery/calldata-archive.d.ts +18 -0
  101. package/dist-runtime/delivery/calldata-archive.js +31 -0
  102. package/dist-runtime/delivery/calldata-archive.js.map +1 -0
  103. package/dist-runtime/delivery/calldata-details.d.ts +47 -0
  104. package/dist-runtime/delivery/calldata-details.js +94 -0
  105. package/dist-runtime/delivery/calldata-details.js.map +1 -0
  106. package/dist-runtime/delivery/calldata-format.d.ts +4 -0
  107. package/dist-runtime/delivery/calldata-format.js +17 -0
  108. package/dist-runtime/delivery/calldata-format.js.map +1 -0
  109. package/dist-runtime/delivery/calldata-preparations.d.ts +13 -0
  110. package/dist-runtime/delivery/calldata-preparations.js +85 -0
  111. package/dist-runtime/delivery/calldata-preparations.js.map +1 -0
  112. package/dist-runtime/delivery/calldata-review.d.ts +44 -0
  113. package/dist-runtime/delivery/calldata-review.js +131 -0
  114. package/dist-runtime/delivery/calldata-review.js.map +1 -0
  115. package/dist-runtime/delivery/codec-pin.d.ts +2 -2
  116. package/dist-runtime/delivery/codec-pin.js +4 -4
  117. package/dist-runtime/delivery/codec-pin.js.map +1 -1
  118. package/dist-runtime/delivery/compiler-files.js +3 -1
  119. package/dist-runtime/delivery/compiler-files.js.map +1 -1
  120. package/dist-runtime/delivery/compiler-pins.js +1 -1
  121. package/dist-runtime/delivery/compiler.js +17 -16
  122. package/dist-runtime/delivery/compiler.js.map +1 -1
  123. package/dist-runtime/delivery/config.d.ts +1 -1
  124. package/dist-runtime/delivery/config.js +27 -2
  125. package/dist-runtime/delivery/config.js.map +1 -1
  126. package/dist-runtime/delivery/configuration-definition.d.ts +9 -0
  127. package/dist-runtime/delivery/configuration-definition.js +33 -6
  128. package/dist-runtime/delivery/configuration-definition.js.map +1 -1
  129. package/dist-runtime/delivery/configuration.js +7 -4
  130. package/dist-runtime/delivery/configuration.js.map +1 -1
  131. package/dist-runtime/delivery/contract-source.d.ts +14 -0
  132. package/dist-runtime/delivery/contract-source.js +138 -0
  133. package/dist-runtime/delivery/contract-source.js.map +1 -0
  134. package/dist-runtime/delivery/custom-format.js +51 -24
  135. package/dist-runtime/delivery/custom-format.js.map +1 -1
  136. package/dist-runtime/delivery/development-inputs.d.ts +14 -0
  137. package/dist-runtime/delivery/development-inputs.js +76 -0
  138. package/dist-runtime/delivery/development-inputs.js.map +1 -0
  139. package/dist-runtime/delivery/development.d.ts +3 -1
  140. package/dist-runtime/delivery/development.js +24 -10
  141. package/dist-runtime/delivery/development.js.map +1 -1
  142. package/dist-runtime/delivery/eoa.d.ts +1 -0
  143. package/dist-runtime/delivery/execution-identity.d.ts +15 -0
  144. package/dist-runtime/delivery/execution-identity.js +33 -0
  145. package/dist-runtime/delivery/execution-identity.js.map +1 -0
  146. package/dist-runtime/delivery/existing-code.js +14 -6
  147. package/dist-runtime/delivery/existing-code.js.map +1 -1
  148. package/dist-runtime/delivery/history-package.d.ts +2 -0
  149. package/dist-runtime/delivery/history-package.js +70 -0
  150. package/dist-runtime/delivery/history-package.js.map +1 -0
  151. package/dist-runtime/delivery/history-registration.d.ts +1 -1
  152. package/dist-runtime/delivery/inputs.js +22 -15
  153. package/dist-runtime/delivery/inputs.js.map +1 -1
  154. package/dist-runtime/delivery/journal.js +18 -10
  155. package/dist-runtime/delivery/journal.js.map +1 -1
  156. package/dist-runtime/delivery/parameter-defaults.d.ts +10 -0
  157. package/dist-runtime/delivery/parameter-defaults.js +86 -0
  158. package/dist-runtime/delivery/parameter-defaults.js.map +1 -0
  159. package/dist-runtime/delivery/parameters.d.ts +2 -0
  160. package/dist-runtime/delivery/parameters.js +22 -0
  161. package/dist-runtime/delivery/parameters.js.map +1 -1
  162. package/dist-runtime/delivery/planning.d.ts +4 -1
  163. package/dist-runtime/delivery/planning.js +19 -3
  164. package/dist-runtime/delivery/planning.js.map +1 -1
  165. package/dist-runtime/delivery/preparation.js +43 -23
  166. package/dist-runtime/delivery/preparation.js.map +1 -1
  167. package/dist-runtime/delivery/production-environment.js +2 -1
  168. package/dist-runtime/delivery/production-environment.js.map +1 -1
  169. package/dist-runtime/delivery/production-finalization.js +23 -9
  170. package/dist-runtime/delivery/production-finalization.js.map +1 -1
  171. package/dist-runtime/delivery/production-intent.d.ts +2 -0
  172. package/dist-runtime/delivery/production-intent.js +16 -0
  173. package/dist-runtime/delivery/production-intent.js.map +1 -0
  174. package/dist-runtime/delivery/production.d.ts +129 -8
  175. package/dist-runtime/delivery/production.js +60 -11
  176. package/dist-runtime/delivery/production.js.map +1 -1
  177. package/dist-runtime/delivery/project-files.d.ts +3 -3
  178. package/dist-runtime/delivery/project-files.js +19 -14
  179. package/dist-runtime/delivery/project-files.js.map +1 -1
  180. package/dist-runtime/delivery/project-rpc.d.ts +19 -0
  181. package/dist-runtime/delivery/project-rpc.js +138 -0
  182. package/dist-runtime/delivery/project-rpc.js.map +1 -0
  183. package/dist-runtime/delivery/project.d.ts +3 -1
  184. package/dist-runtime/delivery/project.js +21 -8
  185. package/dist-runtime/delivery/project.js.map +1 -1
  186. package/dist-runtime/delivery/public-calldata.d.ts +25 -0
  187. package/dist-runtime/delivery/public-calldata.js +97 -0
  188. package/dist-runtime/delivery/public-calldata.js.map +1 -0
  189. package/dist-runtime/delivery/release-graph.d.ts +7 -3
  190. package/dist-runtime/delivery/release-graph.js +58 -25
  191. package/dist-runtime/delivery/release-graph.js.map +1 -1
  192. package/dist-runtime/delivery/release-history-capture.js +22 -26
  193. package/dist-runtime/delivery/release-history-capture.js.map +1 -1
  194. package/dist-runtime/delivery/release-history.d.ts +3 -2
  195. package/dist-runtime/delivery/release-history.js +97 -50
  196. package/dist-runtime/delivery/release-history.js.map +1 -1
  197. package/dist-runtime/delivery/release-inputs.d.ts +33 -0
  198. package/dist-runtime/delivery/release-inputs.js +129 -0
  199. package/dist-runtime/delivery/release-inputs.js.map +1 -0
  200. package/dist-runtime/delivery/release.d.ts +38 -14
  201. package/dist-runtime/delivery/release.js +81 -29
  202. package/dist-runtime/delivery/release.js.map +1 -1
  203. package/dist-runtime/delivery/safe.d.ts +1 -0
  204. package/dist-runtime/delivery/safe.js +13 -2
  205. package/dist-runtime/delivery/safe.js.map +1 -1
  206. package/dist-runtime/delivery/same-fork-baseline.d.ts +1 -1
  207. package/dist-runtime/delivery/same-fork-baseline.js +5 -4
  208. package/dist-runtime/delivery/same-fork-baseline.js.map +1 -1
  209. package/dist-runtime/delivery/setup.d.ts +1 -1
  210. package/dist-runtime/delivery/setup.js +21 -6
  211. package/dist-runtime/delivery/setup.js.map +1 -1
  212. package/dist-runtime/delivery/source.d.ts +1 -0
  213. package/dist-runtime/delivery/source.js +12 -10
  214. package/dist-runtime/delivery/source.js.map +1 -1
  215. package/dist-runtime/delivery/task-identity.d.ts +23 -0
  216. package/dist-runtime/delivery/task-identity.js +109 -0
  217. package/dist-runtime/delivery/task-identity.js.map +1 -0
  218. package/dist-runtime/delivery/toolchain.d.ts +3 -0
  219. package/dist-runtime/delivery/toolchain.js +52 -0
  220. package/dist-runtime/delivery/toolchain.js.map +1 -0
  221. package/dist-runtime/delivery/validation.js +7 -2
  222. package/dist-runtime/delivery/validation.js.map +1 -1
  223. package/dist-runtime/runtime-identity.json +2 -2
  224. package/dist-runtime/vendor/plan-codec/index.cjs +97 -20
  225. package/dist-runtime/vendor/plan-codec/index.d.cts +6 -0
  226. package/dist-runtime/vendor/plan-codec/provenance.json +9 -8
  227. package/dist-runtime/workflow/lib/calls.js +1 -0
  228. package/dist-runtime/workflow/lib/calls.js.map +1 -1
  229. package/dist-runtime/workflow/lib/checkCodeRunner.js +7 -4
  230. package/dist-runtime/workflow/lib/checkCodeRunner.js.map +1 -1
  231. package/dist-runtime/workflow/lib/context.d.ts +1 -0
  232. package/dist-runtime/workflow/lib/create2.d.ts +4 -26
  233. package/dist-runtime/workflow/lib/create2.js +2 -67
  234. package/dist-runtime/workflow/lib/create2.js.map +1 -1
  235. package/dist-runtime/workflow/lib/deploymentInfo.d.ts +2 -0
  236. package/dist-runtime/workflow/lib/deploymentInfo.js +6 -0
  237. package/dist-runtime/workflow/lib/deploymentInfo.js.map +1 -1
  238. package/dist-runtime/workflow/lib/deploymentRecords.d.ts +2 -0
  239. package/dist-runtime/workflow/lib/deploymentRecords.js +1 -1
  240. package/dist-runtime/workflow/lib/deploymentRecords.js.map +1 -1
  241. package/dist-runtime/workflow/lib/externalExecutionScanner.js +2 -1
  242. package/dist-runtime/workflow/lib/externalExecutionScanner.js.map +1 -1
  243. package/dist-runtime/workflow/lib/gateTool.js +2 -2
  244. package/dist-runtime/workflow/lib/gateTool.js.map +1 -1
  245. package/dist-runtime/workflow/lib/gateToolSync.d.ts +3 -0
  246. package/dist-runtime/workflow/lib/gateToolSync.js +5 -0
  247. package/dist-runtime/workflow/lib/gateToolSync.js.map +1 -1
  248. package/dist-runtime/workflow/lib/parameters.js +5 -0
  249. package/dist-runtime/workflow/lib/parameters.js.map +1 -1
  250. package/dist-runtime/workflow/lib/proxy.d.ts +1 -0
  251. package/dist-runtime/workflow/lib/proxy.js.map +1 -1
  252. package/dist-runtime/workflow/run.js +1 -3
  253. package/dist-runtime/workflow/run.js.map +1 -1
  254. package/dist-runtime/workflow/steps/deploy.js +53 -0
  255. package/dist-runtime/workflow/steps/deploy.js.map +1 -1
  256. package/dist-runtime/workflow/steps/upgrade.js +24 -10
  257. package/dist-runtime/workflow/steps/upgrade.js.map +1 -1
  258. package/docs/compiler-qualification.md +8 -2
  259. package/docs/delivery-aggregate.md +2 -0
  260. package/docs/delivery-calldata.md +27 -0
  261. package/docs/delivery-development.md +6 -0
  262. package/docs/delivery-execution-store.md +1 -1
  263. package/docs/delivery-inputs.md +55 -6
  264. package/docs/delivery-parameters.md +1 -1
  265. package/docs/delivery-release.md +77 -7
  266. package/docs/delivery-safe.md +7 -4
  267. package/docs/delivery-setup.md +72 -20
  268. package/docs/delivery-source.md +8 -8
  269. package/docs/direct-package-acceptance.md +2 -0
  270. package/docs/openzeppelin-acceptance.md +86 -0
  271. package/docs/openzeppelin-baseline.json +27 -0
  272. package/docs/openzeppelin-integration.md +115 -0
  273. package/docs/plans/2026-10-28-openzeppelin-toolkit-consolidation.md +396 -0
  274. package/docs/plans/2026-11-02-transparent-proxy-delivery.md +78 -0
  275. package/docs/superpowers/plans/2026-08-17-custody-hardhat-signers.md +1 -1
  276. package/docs/workflow-reference.md +12 -4
  277. package/docs/workflow-runtime.md +6 -0
  278. package/package.json +19 -5
  279. package/runtime/config/hardhatAdapters.ts +2 -1
  280. package/runtime/delivery/aggregate-bootstrap.ts +3 -1
  281. package/runtime/delivery/aggregate-channel.ts +6 -3
  282. package/runtime/delivery/aggregate-diagnostics.ts +63 -0
  283. package/runtime/delivery/aggregate-source.ts +6 -2
  284. package/runtime/delivery/aggregate-worker.ts +15 -5
  285. package/runtime/delivery/aggregate.ts +2 -2
  286. package/runtime/delivery/business-extension.ts +33 -0
  287. package/runtime/delivery/calldata-archive.ts +25 -0
  288. package/runtime/delivery/calldata-details.ts +90 -0
  289. package/runtime/delivery/calldata-format.ts +14 -0
  290. package/runtime/delivery/calldata-preparations.ts +76 -0
  291. package/runtime/delivery/calldata-review.ts +126 -0
  292. package/runtime/delivery/codec-pin.ts +3 -3
  293. package/runtime/delivery/compiler-files.ts +3 -1
  294. package/runtime/delivery/compiler-pins.ts +1 -1
  295. package/runtime/delivery/compiler.ts +18 -17
  296. package/runtime/delivery/config.ts +25 -2
  297. package/runtime/delivery/configuration-definition.ts +34 -7
  298. package/runtime/delivery/configuration.ts +8 -5
  299. package/runtime/delivery/contract-source.ts +112 -0
  300. package/runtime/delivery/custom-format.ts +20 -5
  301. package/runtime/delivery/development-inputs.ts +42 -0
  302. package/runtime/delivery/development.ts +14 -11
  303. package/runtime/delivery/execution-identity.ts +32 -0
  304. package/runtime/delivery/existing-code.ts +7 -6
  305. package/runtime/delivery/history-package.ts +50 -0
  306. package/runtime/delivery/inputs.ts +18 -11
  307. package/runtime/delivery/journal.ts +14 -10
  308. package/runtime/delivery/parameter-defaults.ts +75 -0
  309. package/runtime/delivery/parameters.ts +18 -0
  310. package/runtime/delivery/planning.ts +19 -5
  311. package/runtime/delivery/preparation.ts +17 -1
  312. package/runtime/delivery/production-environment.ts +2 -1
  313. package/runtime/delivery/production-finalization.ts +19 -10
  314. package/runtime/delivery/production-intent.ts +14 -0
  315. package/runtime/delivery/production.ts +51 -11
  316. package/runtime/delivery/project-files.ts +16 -11
  317. package/runtime/delivery/project-rpc.ts +116 -0
  318. package/runtime/delivery/project.ts +19 -7
  319. package/runtime/delivery/public-calldata.ts +74 -0
  320. package/runtime/delivery/release-graph.ts +44 -14
  321. package/runtime/delivery/release-history-capture.ts +19 -9
  322. package/runtime/delivery/release-history.ts +76 -22
  323. package/runtime/delivery/release-inputs.ts +107 -0
  324. package/runtime/delivery/release.ts +56 -18
  325. package/runtime/delivery/safe.ts +14 -3
  326. package/runtime/delivery/same-fork-baseline.ts +5 -4
  327. package/runtime/delivery/setup.ts +20 -8
  328. package/runtime/delivery/source.ts +10 -10
  329. package/runtime/delivery/task-identity.ts +85 -0
  330. package/runtime/delivery/toolchain.ts +48 -0
  331. package/runtime/delivery/validation.ts +7 -2
  332. package/runtime/vendor/plan-codec/index.cjs +97 -20
  333. package/runtime/vendor/plan-codec/index.d.cts +6 -0
  334. package/runtime/vendor/plan-codec/provenance.json +9 -8
  335. package/runtime/workflow/lib/calls.ts +1 -0
  336. package/runtime/workflow/lib/checkCodeRunner.ts +7 -3
  337. package/runtime/workflow/lib/context.ts +1 -0
  338. package/runtime/workflow/lib/create2.ts +7 -108
  339. package/runtime/workflow/lib/deploymentInfo.ts +8 -0
  340. package/runtime/workflow/lib/deploymentRecords.ts +3 -1
  341. package/runtime/workflow/lib/externalExecutionScanner.ts +2 -1
  342. package/runtime/workflow/lib/gateTool.ts +2 -2
  343. package/runtime/workflow/lib/gateToolSync.ts +8 -0
  344. package/runtime/workflow/lib/parameters.ts +4 -0
  345. package/runtime/workflow/lib/proxy.ts +1 -0
  346. package/runtime/workflow/run.ts +1 -2
  347. package/runtime/workflow/steps/deploy.ts +42 -0
  348. package/runtime/workflow/steps/upgrade.ts +19 -11
  349. package/bin/workflow.cjs +0 -19
@@ -6,8 +6,9 @@ import ts from 'typescript';
6
6
  import {existingCodeCoverage,requiredExistingAddresses} from './existing-code';
7
7
  import {yieldCompilerIo} from './compiler-io';
8
8
  import {openDeliveryConfiguration} from './configuration';
9
+ import {aggregateInputHash} from './execution-identity';
9
10
  import {getCreate2Address} from 'ethers';
10
- import {artifactIdentity,BytecodeChecker,prepareEvmManifestCandidate,mergeEvmManifestCandidate,parseTargetManifest,hashStorageLayout,resolveTargetManifestPaths} from 'gate-evm-tools/workflow';
11
+ import {TRANSPARENT_PROXY_ARTIFACT,verifyTransparentAdmin,artifactIdentity,BytecodeChecker,prepareEvmManifestCandidate,mergeEvmManifestCandidate,parseTargetManifest,hashStorageLayout,resolveTargetManifestPaths} from 'gate-evm-tools/workflow';
11
12
  import {canonicalData,canonicalJson,deepFreeze,semanticHash} from '../workflow/lib/canonicalData';
12
13
  import {typedValue,parseTypedValue} from '../workflow/lib/typedValue';
13
14
  import type {VerificationObservation,TypedValue} from '../workflow/lib/evidencePorts';
@@ -24,6 +25,7 @@ import {DeliveryOperationIdentities} from './identities';
24
25
  import {parsePreparationJournal,type PreparationEntry} from './journal';
25
26
  import type {DeliveryCollection} from './planning';
26
27
  import type {DeliveryAggregate,DeliveryAggregateOptions} from './aggregate';
28
+ export {persistDevelopmentInputs} from './development-inputs';
27
29
  import {openAggregateSources} from './aggregate-inputs';
28
30
  import {loadDeliveryPublicTarget} from './config';
29
31
  import {inputDigest,readInputBytes} from './input-files';
@@ -68,7 +70,7 @@ export function expectedDevelopmentAssertions(collection:Pick<DeliveryCollection
68
70
  export function mergeDevelopmentRegistration(input:{
69
71
  registry:unknown;metadata:unknown;base:{registry:ContractInfo;metadata:DeploymentInfo};
70
72
  target:string;deploymentId:string;executionId:string;recordPath:string;updatedAt:string;
71
- changes:readonly (DeploymentChange&{address:string;proxyKind?:'uups'})[];preparations:readonly PreparationEntry[];
73
+ changes:readonly (DeploymentChange&{address:string;proxyKind?:'uups'|'transparent'})[];preparations:readonly PreparationEntry[];
72
74
  }):{registry:ContractInfo;metadata:DeploymentInfo} {
73
75
  const {base,target}=input,registry=validateContractInfo(input.registry),metadata=validateDeploymentInfo(input.metadata);
74
76
  registry[target]??={};metadata.networks[target]??={};
@@ -78,14 +80,14 @@ export function mergeDevelopmentRegistration(input:{
78
80
  const previous=resolveDeployment(registry,target,c.instanceId);
79
81
  if(previous&&previous.key!==c.contractInfoKey){
80
82
  const entry=input.preparations.find(p=>p.stepId===c.stepId),request=entry?.prepared.request;
81
- if(c.kind!=='upgrade'||c.proxyKind!=='uups'||entry?.change.kind!=='upgrade'||request?.kind!=='uups-upgrade'||entry.prepared.plan.kind!=='uups-upgrade'
83
+ if(c.kind!=='upgrade'||!['uups','transparent'].includes(c.proxyKind??'')||entry?.change.kind!=='upgrade'||!request||!(request.kind==='uups-upgrade'||request.kind==='transparent-upgrade')||entry.prepared.plan.kind!==request.kind
82
84
  ||entry.change.instanceId!==c.instanceId||entry.change.contractInfoKey!==c.contractInfoKey||entry.change.actualContract!==c.actualContract
83
85
  ||previous.address.toLowerCase()!==request.proxy.toLowerCase()||previous.address.toLowerCase()!==c.address.toLowerCase()||c.proxyAddress?.toLowerCase()!==request.proxy.toLowerCase())throw Error('Contract candidate key conflict');
84
86
  delete registry[target][previous.key];
85
87
  }
86
88
  if(previous&&previous.address.toLowerCase()!==c.address.toLowerCase()&&c.previousAddress?.toLowerCase()!==previous.address.toLowerCase())throw Error('Contract candidate address conflict');
87
89
  registry[target][c.contractInfoKey]=c.address;
88
- metadata.networks[target][c.instanceId]={contractInfoKey:c.contractInfoKey,address:c.address,actualContract:c.actualContract,...(c.proxyKind?{proxyKind:c.proxyKind,implementationAddress:c.implementationAddress}:{}),source:{kind:'deployment',deploymentId:input.deploymentId,executionId:input.executionId,recordPath:input.recordPath},updatedAt:input.updatedAt};
90
+ metadata.networks[target][c.instanceId]={contractInfoKey:c.contractInfoKey,address:c.address,actualContract:c.actualContract,...(c.proxyKind?{proxyKind:c.proxyKind,implementationAddress:c.implementationAddress,...(c.proxyKind==='transparent'?{proxyAdminAddress:c.proxyAdminAddress,proxyAdminOwner:c.proxyAdminOwner}:{})}:{}),source:{kind:'deployment',deploymentId:input.deploymentId,executionId:input.executionId,recordPath:input.recordPath},updatedAt:input.updatedAt};
89
91
  }
90
92
  return {registry:validateContractInfo(registry),metadata:validateDeploymentInfo(metadata)};
91
93
  }
@@ -107,7 +109,7 @@ export async function createDevelopmentDelivery(options:DevelopmentDeliveryOptio
107
109
  same(preparations.map(p=>({stepId:p.stepId,preparationHash:p.preparationHash,transactionIds:p.mappings.map(m=>m.transactionId),derivedKeys:p.derivedKeys})),plan.deploymentBindings,'Sealed preparation bindings');
108
110
  if(!plan.transactions.length)throw Error('Development acceptance requires actual transactions');
109
111
  const rows=aggregate.inputs.targets;
110
- const computed=semanticHash({version:1,business:aggregate.inputs.business,sourceDefinitions:aggregate.inputs.sourceDefinitions,runtime:aggregate.inputs.runtime,files:aggregate.inputs.files,targets:rows.map(row=>({target:row.target,configuration:row.configuration.configurationRuntimeHash,sourceConfiguration:row.sourceConfiguration.configurationRuntimeHash,compiler:row.compiler.stableDigest,custom:row.custom}))});
112
+ const computed=aggregateInputHash(aggregate);
111
113
  same(plan.deploymentId,aggregate.inputs.business.deploymentId,'Business deployment identity');same(computed,aggregate.inputsHash,'Aggregate input hash');same(plan.inputsHash,computed,'Plan inputs');same(plan.sourceDefinitionHash,aggregate.sourceDefinitionHash,'Plan source');same(semanticHash(aggregate.inputs.sourceDefinitions),aggregate.sourceDefinitionHash,'Source hash');
112
114
  const hre=options.hre,provider={request:(method:string,params:readonly unknown[])=>hre.network.provider.request({method,params:[...params]})};
113
115
  if(options.execution.context.finality.kind==='confirmations'&&BigInt(options.execution.context.finality.depth)<BigInt(Math.max(1,target.finality.confirmations)))throw Error('Development finality below configured policy');
@@ -160,6 +162,7 @@ export async function createDevelopmentDelivery(options:DevelopmentDeliveryOptio
160
162
  if(preparations.length)return;
161
163
  const coverage=pureCoverage(),checker=new BytecodeChecker(hre,{},'evm');
162
164
  for(const row of coverage.expected){const code=await hre.ethers.provider.getCode(row.address),local=await checker.getLocalBytecode(row.contract);if(code==='0x'||!checker.compareBytecode(code,local.bytecode,local.abi,local.immutableReferences).matches)throw Error('Existing development code mismatch');}
165
+ for(const alias of coverage.aliases){const m=base.metadata.networks[plan.target]?.[alias];if(m?.proxyKind==='transparent'){if(!m.proxyAdminAddress||!m.proxyAdminOwner)throw Error('Missing frozen existing Transparent admin');await verifyTransparentAdmin({hre:hre as any,proxy:m.address,admin:m.proxyAdminAddress,owner:m.proxyAdminOwner});}}
163
166
  for(const m of coverage.manifests){if(byteHash(readInputBytes(root,m.file))!==m.hash)throw Error('Existing UUPS manifest changed');const storage=await provider.request('eth_getStorageAt',[m.proxy,'0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc','latest']);if(typeof storage!=='string'||storage.slice(-40).toLowerCase()!==m.implementation.slice(2))throw Error('Existing UUPS implementation changed');}
164
167
  }
165
168
  await assertArtifacts();await assertExistingCode();
@@ -183,16 +186,16 @@ export async function createDevelopmentDelivery(options:DevelopmentDeliveryOptio
183
186
  for(const deployment of p.deployments){
184
187
  if(deployment.initCodeHash&&'factory' in r&&getCreate2Address(r.factory,deployment.salt,deployment.initCodeHash).toLowerCase()!==deployment.address.toLowerCase())throw Error('Prepared CREATE2 address mismatch');
185
188
  const code=await hre.ethers.provider.getCode(deployment.address);if(code==='0x')throw Error('Prepared deployment has no actual code');
186
- const name=deployment.role==='proxy'?'@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy':p.contract;
189
+ const name=deployment.role==='proxy'?(p.proxyKind==='transparent'?TRANSPARENT_PROXY_ARTIFACT:'@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy'):p.contract;
187
190
  const local=await checker.getLocalBytecode(name),comparison=checker.compareBytecode(code,local.bytecode,local.abi,local.immutableReferences);if(!comparison.matches)throw Error(`Prepared deployed code mismatch: ${name}`);
188
191
  }
189
192
  const deployed=p.deployments.find(d=>d.role==='proxy')?.address??('proxy' in r?r.proxy:p.deployments.find(d=>d.role==='contract')?.address);
190
193
  if(!deployed)throw Error('Prepared deployment address missing');
191
- const change={...entry.change,address:deployed,...(p.proxyKind==='uups'?{proxyAddress:deployed,proxyKind:'uups'}:{})};changes.set(change.instanceId,change);
194
+ const change={...entry.change,address:deployed,...(p.proxyKind?{proxyAddress:deployed,proxyKind:p.proxyKind}:{})};changes.set(change.instanceId,change);
192
195
  }
193
- for(const change of changes.values())if(change.proxyKind==='uups'){
196
+ for(const change of changes.values())if(change.proxyKind==='uups'||change.proxyKind==='transparent'){
194
197
  const entry=[...preparations].reverse().find(p=>p.change.instanceId===change.instanceId)!;
195
- const candidate=await prepareEvmManifestCandidate({root,scheme:'evm',network:plan.target,target:plan.target,proxy:change.address,contract:entry.prepared.plan.contract,constructorArgs:change.constructorArgs??[],skipTxHash:true,hre,compile:false});
198
+ const candidate=await prepareEvmManifestCandidate({root,scheme:'evm',network:plan.target,target:plan.target,proxy:change.address,proxyKind:change.proxyKind,proxyAdminAddress:change.proxyAdminAddress,proxyAdminOwner:change.proxyAdminOwner,contract:entry.prepared.plan.contract,constructorArgs:change.constructorArgs??[],skipTxHash:true,hre,compile:false});
196
199
  const expectedImplementation=entry.prepared.plan.deployments.find(d=>d.role==='implementation')?.address??change.implementationAddress;
197
200
  if(!expectedImplementation||candidate.implementation.toLowerCase()!==expectedImplementation.toLowerCase())throw Error('Final UUPS implementation mismatch');
198
201
  same(candidate.artifact,entry.prepared.plan.artifact,'UUPS artifact');change.implementationAddress=candidate.implementation;candidates.push(candidate);
@@ -225,7 +228,7 @@ export async function createDevelopmentDelivery(options:DevelopmentDeliveryOptio
225
228
  }
226
229
  files.push(...manifests.values());return commitDevelopmentFilesLocked({root,executionId:plan.executionId,identity,files},options.onFileCommitted);
227
230
  });
228
- for(const candidate of state.candidates){const manifest=parseTargetManifest(fs.readFileSync(candidate.paths.file)),entry=manifest.impls[candidate.versionKey];if(!entry||![entry.address,...(entry.allAddresses??[])].some(a=>a.toLowerCase()===candidate.implementation)||hashStorageLayout(entry.layout)!==candidate.layoutHash||!manifest.proxies.some(p=>p.address.toLowerCase()===candidate.proxy&&p.kind==='uups'))throw Error('Committed target manifest mismatch');}
231
+ for(const candidate of state.candidates){const manifest=parseTargetManifest(fs.readFileSync(candidate.paths.file)),entry=manifest.impls[candidate.versionKey];if(!entry||![entry.address,...(entry.allAddresses??[])].some(a=>a.toLowerCase()===candidate.implementation)||hashStorageLayout(entry.layout)!==candidate.layoutHash||!manifest.proxies.some(p=>p.address.toLowerCase()===candidate.proxy&&p.kind===candidate.proxyKind))throw Error('Committed target manifest mismatch');}
229
232
  return {journal:result,changes:state.changes,manifests:!preparations.length?pureCoverage().manifests:state.candidates.map(c=>({file:path.relative(root,c.paths.file),hash:byteHash(fs.readFileSync(c.paths.file)),layoutHash:c.layoutHash,proxy:c.proxy,implementation:c.implementation}))};
230
233
  }
231
234
  return Object.freeze({plan,
@@ -242,7 +245,7 @@ export async function createDevelopmentDelivery(options:DevelopmentDeliveryOptio
242
245
  const assertions=await verifyBusiness(),finalized=result.snapshot.transactions.map(t=>t.observation!);
243
246
  const materialization=await materialize(finalized,assertions);
244
247
  const registry=fileBytes(root,'contractInfo.json')!,metadata=fileBytes(root,'deploymentInfo.json')!,effective:Record<string,Record<string,string>>={[plan.target]:{}},expectedCode:ExpectedDevelopmentCode[]=[];
245
- for(const c of materialization.changes){effective[plan.target][c.contractInfoKey]=c.address;const alias=c.contractInfoKey.includes(':')?c.contractInfoKey.split(':')[0]:c.contractInfoKey;expectedCode.push({key:alias,contract:c.actualContract,address:c.implementationAddress??c.address});if(c.proxyKind==='uups')expectedCode.push({key:`${alias}_Proxy`,contract:'ERC1967Proxy',address:c.address});}
248
+ for(const c of materialization.changes){effective[plan.target][c.contractInfoKey]=c.address;const alias=c.contractInfoKey.includes(':')?c.contractInfoKey.split(':')[0]:c.contractInfoKey;expectedCode.push({key:alias,contract:c.actualContract,address:c.implementationAddress??c.address});if(c.proxyKind)expectedCode.push({key:`${alias}_Proxy`,contract:c.proxyKind==='transparent'?'TransparentUpgradeableProxy':'ERC1967Proxy',address:c.address});if(c.proxyKind==='transparent')expectedCode.push({key:`${alias}_ProxyAdmin`,contract:'ProxyAdmin',address:c.proxyAdminAddress});}
246
249
  if(!preparations.length){const coverage=pureCoverage();Object.assign(effective,coverage.effective);expectedCode.push(...coverage.expected);}
247
250
  const acceptancePath=`.gate-delivery/development/${plan.executionId}.acceptance.json`,priorAcceptance=fileBytes(root,acceptancePath);
248
251
  if(priorAcceptance!==null){
@@ -0,0 +1,32 @@
1
+ /** Environment labels are evidence; actual source, dependency and compiler inputs remain binding. */
2
+ import type { RuntimeEvidence } from './configuration-runtime';
3
+ import { parseCustomInputClosure, type CustomInputClosure } from './closure-format';
4
+ import { semanticHash } from '../workflow/lib/canonicalData';
5
+ import type { DeliveryAggregate } from './aggregate';
6
+
7
+ export function runtimeExecutionInput(runtime: RuntimeEvidence): Omit<RuntimeEvidence, 'node'> {
8
+ const { node: _environment, ...inputs } = runtime;
9
+ return inputs;
10
+ }
11
+
12
+ export function compilerExecutionInput<T extends { node: string; platform: string; arch: string; abi: string }>(toolchain: T): Omit<T, 'node' | 'platform' | 'arch' | 'abi'> {
13
+ const { node: _node, platform: _platform, arch: _arch, abi: _abi, ...inputs } = toolchain;
14
+ return inputs;
15
+ }
16
+
17
+ /** Only resolver version and its derived exact hash are omitted; all actual edges/emitted bytes stay. */
18
+ export function customExecutionInput(raw: CustomInputClosure | null): unknown {
19
+ if (raw === null) return null;
20
+ const { closureHash: _exactHash, resolver, ...inputs } = parseCustomInputClosure(raw);
21
+ const { version: _nodeVersion, ...policy } = resolver;
22
+ return { ...inputs, resolver: policy };
23
+ }
24
+
25
+ /** Collection, dev execution and historical validation share the same preimage. */
26
+ export function aggregateInputHash(a: Pick<DeliveryAggregate, 'inputs'>): string {
27
+ return semanticHash({ version: 1, business: a.inputs.business, sourceDefinitions: a.inputs.sourceDefinitions,
28
+ runtime: runtimeExecutionInput(a.inputs.runtime), files: a.inputs.files,
29
+ targets: a.inputs.targets.map(row => ({ target: row.target, configuration: row.configuration.configurationRuntimeHash,
30
+ sourceConfiguration: row.sourceConfiguration.configurationRuntimeHash, compiler: row.compiler.stableDigest,
31
+ custom: customExecutionInput(row.custom) })) });
32
+ }
@@ -1,5 +1,5 @@
1
1
  /** Pure-call coverage from the accepted registration and owned compiler witness. No deployments are invented. */
2
- import {artifactIdentity,parseTargetManifest,hashStorageLayout} from 'gate-evm-tools/workflow';
2
+ import {TRANSPARENT_PROXY_ARTIFACT,PROXY_ADMIN_ARTIFACT,transparentAdminAddress,artifactIdentity,parseTargetManifest,hashStorageLayout} from 'gate-evm-tools/workflow';
3
3
  import {canonicalJson,semanticHash} from '../workflow/lib/canonicalData';
4
4
  import {validateContractInfo} from '../workflow/lib/deployments';
5
5
  import {validateDeploymentInfo} from '../workflow/lib/deploymentInfo';
@@ -26,10 +26,11 @@ export function existingCodeCoverage(input:{target:string;addresses:string[];reg
26
26
  const [key]=matches[0],alias=key.split(':')[0],m=metadata[alias],contract=m?.actualContract??key.split(':').at(-1)!;
27
27
  if(m&&(m.contractInfoKey!==key||m.address.toLowerCase()!==address))throw Error('Existing code metadata registration mismatch');
28
28
  aliases.push(alias);effective[input.target][key]=address;
29
- if(m?.proxyKind&&m.proxyKind!=='uups')throw Error('Unsupported existing proxy kind');
30
- if(m?.proxyKind==='uups'){
31
- const implementation=m.implementationAddress!.toLowerCase();add(alias,contract,implementation);add(`${alias}_Proxy`,'ERC1967Proxy',address);
32
- const owned=input.manifests.flatMap(file=>{const manifest=parseTargetManifest(Buffer.from(file.contents));const proxies=manifest.proxies.filter(p=>p.address.toLowerCase()===address),impls=Object.entries(manifest.impls).filter(([,v])=>v&&[v.address,...(v.allAddresses??[])].some(a=>a.toLowerCase()===implementation));return proxies.length===1&&proxies[0].kind==='uups'&&impls.length===1?[{file:file.path,hash:byteHash(file.contents),layoutHash:hashStorageLayout(impls[0][1]!.layout),proxy:address,implementation}]:[];});
29
+ if(m?.proxyKind&&m.proxyKind!=='uups'&&m.proxyKind!=='transparent')throw Error('Unsupported existing proxy kind');
30
+ if(m?.proxyKind==='uups'||m?.proxyKind==='transparent'){
31
+ const implementation=m.implementationAddress!.toLowerCase();add(alias,contract,implementation);add(`${alias}_Proxy`,m.proxyKind==='transparent'?TRANSPARENT_PROXY_ARTIFACT:'ERC1967Proxy',address);
32
+ if(m.proxyKind==='transparent'){if(m.proxyAdminAddress?.toLowerCase()!==transparentAdminAddress(address)||!m.proxyAdminOwner)throw Error('Missing existing Transparent admin identity');add(`${alias}_ProxyAdmin`,PROXY_ADMIN_ARTIFACT,m.proxyAdminAddress);}
33
+ const owned=input.manifests.flatMap(file=>{const manifest=parseTargetManifest(Buffer.from(file.contents));const proxies=manifest.proxies.filter(p=>p.address.toLowerCase()===address),impls=Object.entries(manifest.impls).filter(([,v])=>v&&[v.address,...(v.allAddresses??[])].some(a=>a.toLowerCase()===implementation));return proxies.length===1&&proxies[0].kind===m.proxyKind&&impls.length===1?[{file:file.path,hash:byteHash(file.contents),layoutHash:hashStorageLayout(impls[0][1]!.layout),proxy:address,implementation}]:[];});
33
34
  if(owned.length!==1)throw Error('Missing unique sealed existing UUPS manifest');manifests.push(owned[0]);
34
35
  }else add(alias,contract,address);
35
36
  }
@@ -39,6 +40,6 @@ export function existingCodeCoverage(input:{target:string;addresses:string[];reg
39
40
  /** Called only by the owned worker while the actual compiler artifact reader is installed. */
40
41
  export async function collectExistingCodeArtifacts(input:{target:string;addresses:string[];registry:unknown;metadata:unknown;readArtifact(name:string):Promise<unknown>}){
41
42
  const registry=validateContractInfo(input.registry)[input.target]??{},metadata=validateDeploymentInfo(input.metadata).networks[input.target]??{},names=new Set<string>();
42
- for(const address of new Set(input.addresses.map(a=>a.toLowerCase()))){const entries=Object.entries(registry).filter(([,a])=>a.toLowerCase()===address);if(entries.length!==1)throw Error('Existing code target requires unique frozen registration');const [key]=entries[0],m=metadata[key.split(':')[0]];names.add(m?.actualContract??key.split(':').at(-1)!);if(m?.proxyKind==='uups')names.add('@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy');}
43
+ for(const address of new Set(input.addresses.map(a=>a.toLowerCase()))){const entries=Object.entries(registry).filter(([,a])=>a.toLowerCase()===address);if(entries.length!==1)throw Error('Existing code target requires unique frozen registration');const [key]=entries[0],m=metadata[key.split(':')[0]];names.add(m?.actualContract??key.split(':').at(-1)!);if(m?.proxyKind==='uups'||m?.proxyKind==='transparent'){names.add(m.proxyKind==='transparent'?TRANSPARENT_PROXY_ARTIFACT:'@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy');if(m.proxyKind==='transparent')names.add(PROXY_ADMIN_ARTIFACT);}}
43
44
  for(const name of names)await input.readArtifact(name);
44
45
  }
@@ -0,0 +1,50 @@
1
+ /** Verify retained producer bytes in memory. Historical code is never extracted or executed. */
2
+ import {createHash} from 'node:crypto';
3
+ import {gunzipSync} from 'node:zlib';
4
+ import {byteHash} from './materialization';
5
+ import {object,portablePath} from './protocol';
6
+ import {canonicalJson} from '../workflow/lib/canonicalData';
7
+ import type {DeliveryAggregate} from './aggregate';
8
+
9
+ export function readHistoricalPackage(archive:Buffer,archiveFile:string,aggregate:DeliveryAggregate):ReadonlyMap<string,Buffer> {
10
+ if(archiveFile!==`.gate-delivery/packages/${byteHash(archive)}.json.gz`)throw Error('Historical archive content address mismatch');
11
+ const snapshot=object(JSON.parse(gunzipSync(archive,{maxOutputLength:128*1024*1024}).toString()),'historical package snapshot',['schema','version','runtimeIdentity','observedPackage','files']);
12
+ if(snapshot.schema!=='gate-delivery-package-snapshot'||snapshot.version!==2||!Array.isArray(snapshot.files))throw Error('Invalid historical package snapshot archive');
13
+ const original=aggregate.inputs.runtime.package;
14
+ const same=(a:unknown,b:unknown,label:string)=>{if(canonicalJson(a)!==canonicalJson(b))throw Error(`${label} mismatch`);};
15
+ same(snapshot.observedPackage,original,'Historical snapshot provenance');
16
+ same(snapshot.runtimeIdentity,aggregate.inputs.runtime.declared,'Historical snapshot runtime');
17
+ const files=new Map<string,Buffer>();
18
+ for(const raw of snapshot.files){
19
+ const file=object(raw,'historical package member',['path','digest','base64']),relative=portablePath(file.path,'historical package member');
20
+ if(relative.split('/').includes('node_modules')||files.has(relative)||typeof file.base64!=='string')throw Error('Invalid historical package member');
21
+ const bytes=Buffer.from(file.base64,'base64');
22
+ if(bytes.toString('base64')!==file.base64||byteHash(bytes)!==file.digest)throw Error('Historical snapshot archive bytes mismatch');
23
+ files.set(relative,bytes);
24
+ }
25
+ const payload=[...files].map(([path,bytes])=>({path,digest:byteHash(bytes)}));
26
+ same(payload,original.payload,'Historical archive complete payload');
27
+ same(byteHash(payload.map(f=>`${f.path}\0${f.digest}\n`).join('')),original.payloadDigest,'Historical payload digest');
28
+ // Match the producer's sorted directory traversal, including file/directory prefix ordering.
29
+ const children=new Map<string,Set<string>>();
30
+ for(const relative of files.keys()){
31
+ const parts=relative.split('/');let directory='';
32
+ for(let i=0;i<parts.length;i++){
33
+ if(files.has(directory))throw Error('Historical package file/directory collision');
34
+ if(!children.has(directory))children.set(directory,new Set());
35
+ children.get(directory)!.add(parts[i]);directory=directory?`${directory}/${parts[i]}`:parts[i];
36
+ }
37
+ }
38
+ const digest=createHash('sha256');
39
+ const visit=(directory:string)=>{
40
+ const names=children.get(directory);if(!names)throw Error('Historical executable directory missing');
41
+ for(const name of [...names].sort()){
42
+ const relative=`${directory}/${name}`,bytes=files.get(relative);
43
+ if(bytes){if(/\.(?:c?js)$/.test(relative)){digest.update(relative);digest.update(bytes);}}
44
+ else visit(relative);
45
+ }
46
+ };
47
+ for(const directory of ['dist-runtime','dist','dist-cjs','bin'])visit(directory);
48
+ same(digest.digest('hex'),aggregate.inputs.runtime.declared.digest,'Historical executable runtime digest');
49
+ return files;
50
+ }
@@ -11,6 +11,8 @@ import { resolveDeliveryParameters, consumeDeliveryParameters, type ResolvedDeli
11
11
  import { validateDeploySaveAs, type WorkflowStep } from '../workflow/lib/parameters';
12
12
  import { canonicalJson, deepFreeze, semanticHash, exactObject, nonempty } from '../workflow/lib/canonicalData';
13
13
  import type { DeepReadonly } from './source';
14
+ import { parseDeploymentRequirementRef } from './task-identity';
15
+ import { resolveParameterTargets } from './parameter-defaults';
14
16
 
15
17
  export interface DeliveryInputOptions {
16
18
  workspaceRoot: string;
@@ -83,20 +85,29 @@ export function openDeliveryInputs(raw: DeliveryInputOptions): DeliveryInputHand
83
85
  files.push({ path: relative, digest: inputDigest(bytes) });
84
86
  return parseInputDocument(bytes, format);
85
87
  };
86
- const task = exactObject(read('task.yaml', 'yaml'), ['version', 'id', 'developmentNetwork', 'releaseTargetNetworks'], 'task.yaml');
88
+ const task = object(read('task.yaml', 'yaml'), 'task.yaml', ['version', 'id', 'developmentNetwork', 'releaseTargetNetworks', 'requirementRef', 'productionRequirementRef', 'referenceDeploymentId']);
87
89
  if (task.version !== 1 || task.id !== deploymentId) throw new Error('Task version/deployment identity mismatch');
90
+ same(parseDeploymentRequirementRef(task.requirementRef), scope.requirementRef, 'Task requirementRef');
91
+ same(task.referenceDeploymentId ?? null, scope.referenceDeploymentId ?? null, 'Task referenceDeploymentId');
88
92
  same(task.developmentNetwork, scope.developmentNetwork, 'Task developmentNetwork');
89
- same(task.releaseTargetNetworks, scope.releaseTargetNetworks, 'Task releaseTargetNetworks');
93
+ const release = task.releaseTargetNetworks as string[];
94
+ if (!Array.isArray(release) || new Set(release).size !== release.length) throw Error('Invalid task releaseTargetNetworks');
95
+ for (const network of release) if(typeof network !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(network) || ['__proto__','prototype','constructor'].includes(network)) throw Error('Invalid release target');
96
+ if (input.request.environment === 'dev') {
97
+ if (!(scope.releaseTargetNetworks as string[]).every(network => release.includes(network))) throw Error('Task removed a development-declared release target');
98
+ } else {
99
+ same(release, scope.releaseTargetNetworks, 'Task releaseTargetNetworks');
100
+ same(task.productionRequirementRef === undefined ? null : parseDeploymentRequirementRef(task.productionRequirementRef), scope.productionRequirementRef ?? null, 'Task productionRequirementRef');
101
+ }
90
102
  const manifest = object(read('manifest.yaml', 'yaml'), 'manifest.yaml', ['id', 'description', 'steps']);
91
103
  if (manifest.id !== deploymentId) throw new Error('Manifest deployment identity mismatch');
92
104
  if (manifest.description !== undefined) nonempty(manifest.description, 'manifest description');
93
105
  const steps = parseSteps(manifest.steps);
94
106
  const schema = object(read('parameters.schema.json', 'json'), 'parameters schema');
95
- const values = exactObject(read('parameters.yaml', 'yaml'), ['params'], 'parameters.yaml');
96
- const params = object(values.params, 'target parameters');
97
- const provenance = exactObject(read('parameters.provenance.json', 'json'), ['version', 'producers', 'targets'], 'parameters provenance');
98
- if (provenance.version !== 1) throw new Error('Unsupported provenance version');
99
- const definitions = object(provenance.producers, 'producers'), observations = object(provenance.targets, 'provenance targets');
107
+ const dev = scope.developmentNetwork as string;
108
+ const all = [dev, ...release];
109
+ const { params, observations, definitions } = resolveParameterTargets(
110
+ read('parameters.yaml', 'yaml'), read('parameters.provenance.json', 'json'), all);
100
111
  for (const [id, raw] of Object.entries(definitions)) {
101
112
  safeId(id, 'producer ID');
102
113
  const definition = exactObject(raw, ['version', 'module'], 'producer');
@@ -104,10 +115,6 @@ export function openDeliveryInputs(raw: DeliveryInputOptions): DeliveryInputHand
104
115
  const module = portablePath(definition.module, 'producer module');
105
116
  if (!module.startsWith(`${businessRoot}/`)) throw new Error('Producer module is outside deployment business root');
106
117
  }
107
- const dev = scope.developmentNetwork as string, release = scope.releaseTargetNetworks as string[];
108
- const all = [dev, ...release];
109
- for (const name of [...Object.keys(params), ...Object.keys(observations)]) if (!all.includes(name)) throw new Error('Unknown parameter target');
110
- for (const value of Object.values(observations)) exactObject(value, ['manual', 'computed'], 'target provenance');
111
118
  const selected = input.selection === 'development' ? [dev] : input.selection === 'release' ? release : all;
112
119
  // Both the digest and every public projection use these exact buffers. Reopening
113
120
  // for projection would permit an A→B→A edit to bind B's values to A's digest.
@@ -14,7 +14,7 @@ import type { DerivedBindings } from './bindings';
14
14
  import { matchesSameForkInitial, sameForkBaselineDigest } from './same-fork-baseline';
15
15
  export interface PreparationEntry extends PreparationInput { requestHash: string; gateToolPlanHash: string; mappings: PreparationMapping[]; preparationHash: string }
16
16
  export interface JournalIdentity { target: string; chainId: string; expectedStepIds: readonly string[] }
17
- const addressKeys = ['address', 'proxyAddress', 'implementationAddress', 'preparedImplementationAddress', 'placeholderImplementationAddress', 'factory', 'multicall', 'expectedAddress', 'predictedAddress', 'previousAddress'];
17
+ const addressKeys = ['address', 'proxyAddress', 'proxyAdminAddress', 'proxyAdminOwner', 'implementationAddress', 'preparedImplementationAddress', 'placeholderImplementationAddress', 'factory', 'multicall', 'expectedAddress', 'predictedAddress', 'previousAddress'];
18
18
  const stringKeys = ['stepId', 'instanceId', 'actualContract', 'contractInfoKey', 'strategy', 'proxyKind', 'implementationSalt', 'salt', 'redeployReason'];
19
19
  // Prepared changes cannot carry runtime reuse observations, receipts, candidate lifecycle, sync or success markers.
20
20
  const changeKeys = [...addressKeys, ...stringKeys, 'kind', 'constructorArgs', 'leadingZeroBytes', 'gateTool'];
@@ -42,10 +42,10 @@ function normalizeInput(raw: unknown, identity: JournalIdentity): PreparationInp
42
42
  if (!requestPath.endsWith(`/${stepId}-request.json`) || !planPath.endsWith(`/${stepId}-plan.json`)) throw new Error('Preparation step/ref mismatch');
43
43
  if (request.scheme !== 'evm' || plan.scheme !== 'evm') throw new Error('Delivery preparation must use EVM');
44
44
  if (plan.requestHash !== hashPreparationRequest(request) || plan.kind !== request.kind || plan.network !== request.network || plan.target !== request.target || plan.contract !== request.contract || plan.target !== identity.target || plan.chainId !== identity.chainId) throw new Error('Preparation request/plan identity mismatch');
45
- if (change.stepId !== stepId || (change.kind === 'upgrade') !== (plan.kind === 'uups-upgrade') || change.actualContract !== plan.artifact.contractName || (plan.contract.includes(':') && plan.contract !== `${plan.artifact.sourceName}:${plan.artifact.contractName}`)) throw new Error('Preparation change/step/artifact identity mismatch');
45
+ if (change.stepId !== stepId || (change.kind === 'upgrade') !== (plan.kind === 'uups-upgrade' || plan.kind === 'transparent-upgrade') || change.actualContract !== plan.artifact.contractName || (plan.contract.includes(':') && plan.contract !== `${plan.artifact.sourceName}:${plan.artifact.contractName}`)) throw new Error('Preparation change/step/artifact identity mismatch');
46
46
  if (canonicalJson(plan.transactions.map(t => t.purpose)) !== canonicalJson(expectedTransactionPurposes(plan))) throw new Error('Preparation transaction purposes/order mismatch');
47
47
  if (!sameAddress(change.factory, request.factory) || change.contractInfoKey !== contractInfoKey(change.instanceId, change.actualContract)) throw new Error('Prepared factory/registry identity mismatch');
48
- if (change.strategy !== (plan.kind === 'uups-upgrade' ? 'gate-tool' : 'create2')) throw new Error('Invalid prepared strategy');
48
+ if (change.strategy !== ((plan.kind === 'uups-upgrade' || plan.kind === 'transparent-upgrade') ? 'gate-tool' : 'create2')) throw new Error('Invalid prepared strategy');
49
49
  const role = (name: string) => { const matches = plan.deployments.filter(d => d.role === name); if (matches.length !== 1) throw new Error(`Missing/duplicate preparation ${name}`); return matches[0]; };
50
50
  const optionalAddress = (key: keyof DeploymentChange, expected: string) => {
51
51
  if (Object.hasOwn(change, key) && !sameAddress(change[key], expected)) throw new Error(`Prepared ${key} does not match its canonical address`);
@@ -61,17 +61,21 @@ function normalizeInput(raw: unknown, identity: JournalIdentity): PreparationInp
61
61
  if (Object.hasOwn(change, 'constructorArgs') && canonicalJson(change.constructorArgs) !== canonicalJson(request.constructorArgs)) throw new Error('Prepared constructorArgs differ from canonical request');
62
62
  if (request.kind === 'create2-deploy') {
63
63
  const deployment = role('contract');
64
- rejectFields('proxyAddress', 'implementationAddress', 'preparedImplementationAddress', 'placeholderImplementationAddress', 'implementationSalt');
64
+ rejectFields('proxyAddress', 'implementationAddress', 'preparedImplementationAddress', 'placeholderImplementationAddress', 'implementationSalt', 'proxyAdminAddress', 'proxyAdminOwner');
65
65
  if (change.proxyKind !== undefined || deployment.salt !== request.salt || change.salt !== request.salt || !sameAddress(change.predictedAddress, deployment.address)) throw new Error('Prepared CREATE2 request/deployment mismatch');
66
66
  optionalAddress('address', deployment.address);
67
67
  deploymentPolicy(request.addressPolicy, deployment.address);
68
68
  } else {
69
69
  const implementation = role('implementation');
70
- if (change.proxyKind !== 'uups' || !sameAddress(change.implementationAddress, implementation.address) || implementation.salt !== request.implementationSalt) throw new Error('Prepared implementation mismatch');
70
+ if (change.proxyKind !== request.proxyKind || !sameAddress(change.implementationAddress, implementation.address) || implementation.salt !== request.implementationSalt) throw new Error('Prepared implementation mismatch');
71
71
  optionalAddress('preparedImplementationAddress', implementation.address);
72
- if (request.kind === 'uups-placeholder-deploy') {
72
+ if(request.proxyKind==='transparent'){
73
+ if(!sameAddress(change.proxyAdminAddress,plan.proxyAdmin?.address)||!sameAddress(change.proxyAdminOwner,request.proxyAdminOwner)||!sameAddress(plan.proxyAdmin?.owner,request.proxyAdminOwner))throw Error('Prepared Transparent ProxyAdmin mismatch');
74
+ }else rejectFields('proxyAdminAddress','proxyAdminOwner');
75
+ if (request.kind === 'uups-placeholder-deploy' || request.kind === 'transparent-deploy') {
73
76
  const proxy = role('proxy');
74
- if (proxy.salt !== request.proxySalt || change.salt !== request.proxySalt || !sameAddress(change.predictedAddress, proxy.address) || !sameAddress(change.placeholderImplementationAddress, request.placeholderImplementation)) throw new Error('Prepared proxy mismatch');
77
+ if (proxy.salt !== request.proxySalt || change.salt !== request.proxySalt || !sameAddress(change.predictedAddress, proxy.address) || (request.kind==='uups-placeholder-deploy'&&!sameAddress(change.placeholderImplementationAddress, request.placeholderImplementation))) throw new Error('Prepared proxy mismatch');
78
+ if(request.kind==='transparent-deploy')rejectFields('placeholderImplementationAddress');
75
79
  optionalAddress('address', proxy.address);
76
80
  optionalAddress('proxyAddress', proxy.address);
77
81
  deploymentPolicy(request.proxyAddressPolicy, proxy.address);
@@ -132,9 +136,9 @@ export function parsePreparationJournal(raw: unknown, transactions: readonly Rel
132
136
  if (canonicalJson(entries.map(e => e.stepId)) !== canonicalJson(identity.expectedStepIds)) throw new Error('missing, extra or duplicate preparation steps');
133
137
  for (const [index, entry] of entries.entries()) {
134
138
  const {request,plan} = entry.prepared;
135
- if (request.kind === 'uups-upgrade' && plan.validation.kind === 'uups-upgrade' && plan.validation.sameForkBaselineDigest !== undefined) {
139
+ if ((request.kind === 'uups-upgrade' || request.kind === 'transparent-upgrade') && (plan.validation.kind === 'uups-upgrade' || plan.validation.kind === 'transparent-upgrade') && plan.validation.sameForkBaselineDigest !== undefined) {
136
140
  const validation = plan.validation;
137
- const prior = entries.slice(0,index).filter(e => matchesSameForkInitial(e.prepared,request.target,plan.chainId,request.proxy,validation.currentImplementation));
141
+ const prior = entries.slice(0,index).filter(e => matchesSameForkInitial(e.prepared,request.target,plan.chainId,request.proxy,validation.currentImplementation,request.proxyKind));
138
142
  if (prior.length !== 1 || sameForkBaselineDigest(prior[0].prepared,validation.oldLayoutHash) !== validation.sameForkBaselineDigest) throw new Error('Same-fork upgrade requires its exact prior initial preparation');
139
143
  }
140
144
  }
@@ -189,7 +193,7 @@ export class PreparationJournal implements PreparationSink {
189
193
  assertUpgradeBaseline(proxy: string): boolean {
190
194
  const matches = this.inputs.filter(i => matchesSameForkInitial(i.prepared,this.identity.target,this.identity.chainId,proxy));
191
195
  if (!matches.length) return false;
192
- if (matches.length !== 1 || !this.qualifiedSameFork?.(matches[0].prepared)) throw new Error('Same-fork UUPS upgrade requires a complete validated immutable OZ layout baseline; unsupported without that evidence');
196
+ if (matches.length !== 1 || !this.qualifiedSameFork?.(matches[0].prepared)) throw new Error('Same-fork proxy upgrade requires a complete validated immutable OZ layout baseline; unsupported without that evidence');
193
197
  return true;
194
198
  }
195
199
  seal(transactions: readonly ReleaseExecutionTransaction[], derived: DerivedBindings): PreparationEntry[] {
@@ -0,0 +1,75 @@
1
+ /** Expand task-owned defaults before schema/provenance validation. Never a production override port. */
2
+ import { ownPath, pointerPart } from './data';
3
+ import { object } from './protocol';
4
+ import { canonicalJson, exactObject } from '../workflow/lib/canonicalData';
5
+
6
+ type Observations = { manual: Record<string, unknown>; computed: Record<string, unknown> };
7
+ const record = (value: unknown): value is Record<string, unknown> =>
8
+ value !== null && typeof value === 'object' && !Array.isArray(value);
9
+ function observations(raw: unknown): Observations {
10
+ const value = exactObject(raw, ['manual', 'computed'], 'target provenance');
11
+ return { manual: object(value.manual, 'manual observations'), computed: object(value.computed, 'computed observations') };
12
+ }
13
+ function leaves(value: unknown, path = '', result = new Map<string, unknown>()): Map<string, unknown> {
14
+ const entries = value !== null && typeof value === 'object' ? Object.entries(value) : [];
15
+ if (!entries.length) result.set(path, value);
16
+ else for (const [key, child] of entries) leaves(child, `${path}/${pointerPart(key)}`, result);
17
+ return result;
18
+ }
19
+ function merge(base: Record<string, unknown>, override: Record<string, unknown>): Record<string, unknown> {
20
+ return Object.fromEntries([...new Set([...Object.keys(base), ...Object.keys(override)])].map(key => [key,
21
+ !Object.hasOwn(override, key) ? base[key]
22
+ : Object.hasOwn(base, key) && record(base[key]) && record(override[key]) ? merge(base[key], override[key])
23
+ : override[key],
24
+ ]));
25
+ }
26
+ /** Only leaves actually inherited from defaults may inherit default observations. Arrays replace as a unit. */
27
+ function inheritedLeaves(base: unknown, override: unknown, path = '', result = new Set<string>()): Set<string> {
28
+ if (!record(base) || !record(override)) return result;
29
+ for (const [key, value] of Object.entries(base)) {
30
+ const child = `${path}/${pointerPart(key)}`;
31
+ if (!Object.hasOwn(override, key)) for (const pointer of leaves(value, child).keys()) result.add(pointer);
32
+ else if (record(value) && record(override[key])) inheritedLeaves(value, override[key], child, result);
33
+ }
34
+ // The empty root/container is itself a schema leaf.
35
+ if (!Object.keys(base).length && !Object.keys(override).length) result.add(path);
36
+ return result;
37
+ }
38
+
39
+ export function resolveParameterTargets(rawValues: unknown, rawProvenance: unknown, networks: readonly string[]): {
40
+ params: Record<string, unknown>; observations: Record<string, Observations>; definitions: Record<string, unknown>;
41
+ } {
42
+ const values = object(rawValues, 'parameters.yaml', ['defaults', 'params']);
43
+ const params = object(ownPath(values, ['params'], 'target parameters'), 'target parameters');
44
+ const provenance = object(rawProvenance, 'parameters provenance', ['version', 'producers', 'defaults', 'targets']);
45
+ if (provenance.version !== 1) throw new Error('Unsupported provenance version');
46
+ const definitions = object(provenance.producers, 'producers'), targets = object(provenance.targets, 'provenance targets');
47
+ for (const name of [...Object.keys(params), ...Object.keys(targets)])
48
+ if (!networks.includes(name)) throw new Error('Unknown parameter target');
49
+ const observed = Object.fromEntries(Object.entries(targets).map(([name, value]) => [name, observations(value)]));
50
+ if (!Object.hasOwn(values, 'defaults')) {
51
+ if (Object.hasOwn(provenance, 'defaults')) throw new Error('Default provenance requires parameter defaults');
52
+ return { params, observations: observed, definitions };
53
+ }
54
+ const defaults = object(values.defaults, 'parameter defaults');
55
+ const shared = Object.hasOwn(provenance, 'defaults') ? observations(provenance.defaults) : { manual: {}, computed: {} };
56
+ const defaultLeaves = leaves(defaults);
57
+ for (const kind of ['manual', 'computed'] as const) for (const [path, raw] of Object.entries(shared[kind])) {
58
+ if (!defaultLeaves.has(path)) throw new Error(`Unused default parameter observation at ${path}`);
59
+ const observation = exactObject(raw, kind === 'manual' ? ['source', 'value'] : ['producer', 'version', 'inputs', 'output'], 'default observation');
60
+ if (canonicalJson(observation[kind === 'manual' ? 'value' : 'output']) !== canonicalJson(defaultLeaves.get(path)))
61
+ throw new Error(`Default observation mismatch at ${path}`);
62
+ }
63
+ const effective = Object.fromEntries(networks.map(name => {
64
+ const override = Object.hasOwn(params, name) ? object(params[name], 'network parameter overrides') : {};
65
+ return [name, merge(defaults, override)];
66
+ }));
67
+ const effectiveObservations = Object.fromEntries(networks.map(name => {
68
+ const override = Object.hasOwn(params, name) ? params[name] : {};
69
+ const inherited = inheritedLeaves(defaults, override), local = Object.hasOwn(observed, name) ? observed[name] : { manual: {}, computed: {} };
70
+ return [name, Object.fromEntries((['manual', 'computed'] as const).map(kind => [kind, {
71
+ ...Object.fromEntries(Object.entries(shared[kind]).filter(([path]) => inherited.has(path))), ...local[kind],
72
+ }])) as Observations];
73
+ }));
74
+ return { params: effective, observations: effectiveObservations, definitions };
75
+ }
@@ -324,6 +324,24 @@ export function resolveDeliveryParameters(
324
324
  const body = { version: 1 as const, ...input, provenance };
325
325
  return deepFreeze({ ...body, identity: semanticHash(body) });
326
326
  }
327
+ /** Read-only migration check, never a producer receipt or production authority. */
328
+ export function validateHistoricalParameterExtension(previous: ResolvedDeliveryParameters, current: ParameterInputs): ResolvedDeliveryParameters {
329
+ consumeDeliveryParameters(previous, previous.identity);
330
+ const input = strictData({schema: current.schema, target: current.target, values: current.values,
331
+ sources: current.sources ?? {}, manual: current.manual ?? {}, computed: current.computed ?? {}});
332
+ if (input.target !== previous.target) throw Error('Historical parameter target changed');
333
+ // A historical consumer cannot rerun or grant authority to a newly introduced producer.
334
+ for (const [pointer, observation] of Object.entries(input.computed)) {
335
+ if (canonicalJson(observation) !== canonicalJson(previous.computed[pointer] ?? null)) throw Error('Historical computed parameter changed; new development acceptance required');
336
+ }
337
+ const provenance = attest(input);
338
+ for (const leaf of previous.provenance) {
339
+ const next = provenance.find(candidate => candidate.path === leaf.path);
340
+ if (!next || canonicalJson(next) !== canonicalJson(leaf)) throw Error(`Historical parameter value/provenance changed: ${leaf.path}`);
341
+ }
342
+ const body = {version: 1 as const, ...input, provenance};
343
+ return deepFreeze({...body, identity: semanticHash(body)});
344
+ }
327
345
  /** Consume a previously trusted identity; no fill-in, override, or producer invocation. */
328
346
  export function consumeDeliveryParameters(
329
347
  raw: ResolvedDeliveryParameters,
@@ -1,4 +1,6 @@
1
1
  import { yieldCompilerIo } from './compiler-io';
2
+ import { createCalldataInvocation, reviewTransaction, parseCalldataReviews, type CalldataTransactionReview } from './calldata-review';
3
+ import { preparationCalldataReviews } from './calldata-preparations';
2
4
  import {assertOwnedTargetWorker} from './aggregate-bootstrap';
3
5
  import type { ReferenceObservation } from "./references";
4
6
  import { createDeliveryValidation } from "./validation";
@@ -67,6 +69,7 @@ export interface DeliveryRuntimeEvidence {
67
69
  }
68
70
  export interface DeliveryCollection {
69
71
  plan: DeliveryPlan;
72
+ calldata: CalldataTransactionReview[];
70
73
  preparations: PreparationEntry[];
71
74
  verification: VerificationObservation[];
72
75
  runtimeEvidence: DeliveryRuntimeEvidence;
@@ -95,14 +98,14 @@ export interface DeliveryPlanningOptions {
95
98
  identities: PlanningIdentityPort;
96
99
  steps: readonly WorkflowStep[];
97
100
  derivationSeed: string;
98
- expected?: Pick<DeliveryCollection, "plan" | "preparations" | "verification">;
101
+ expected?: Pick<DeliveryCollection, "plan" | "preparations" | "verification"> & Partial<Pick<DeliveryCollection, 'calldata'>>;
99
102
  completedTransactions?: CompletedExecutionTransaction[];
100
103
  customSession?: CustomPlanningInputSession;
101
104
  }
102
105
  export interface StagedDeliveryCollection {
103
106
  readonly payload: Omit<DeliveryPlanBody,'inputsHash'>;
104
107
  readonly invariantHash:string;
105
- readonly snapshot: {payload:Omit<DeliveryPlanBody,'inputsHash'>;preparations:PreparationEntry[];verification:VerificationObservation[];runtimeEvidence:Omit<DeliveryRuntimeEvidence,'forkAudit'>&{forkAudit:Omit<ForkAuditEvidence,'planHash'|'evidenceHash'>}};
108
+ readonly snapshot: {payload:Omit<DeliveryPlanBody,'inputsHash'>;calldata:CalldataTransactionReview[];preparations:PreparationEntry[];verification:VerificationObservation[];runtimeEvidence:Omit<DeliveryRuntimeEvidence,'forkAudit'>&{forkAudit:Omit<ForkAuditEvidence,'planHash'|'evidenceHash'>}};
106
109
  assertUnchanged(): Promise<void>;
107
110
  bind(inputsHash:string): DeliveryCollection;
108
111
  close():void;
@@ -224,6 +227,7 @@ async function collectOwned(input:DeliveryPlanningOptions,staging:boolean):Promi
224
227
  });
225
228
  const verification = new VerificationJournal([]);
226
229
  const pendingObservations: DeliveryRuntimeEvidence["pendingUupsReuse"] = [];
230
+ const callReviews = new Map<string, CalldataTransactionReview>();
227
231
  const operationIds = new DeliveryOperationIdentities();
228
232
  const references: DeliveryRuntimeEvidence["references"] = [];
229
233
  const customBindings: CustomEvidence[] = [],
@@ -249,6 +253,10 @@ async function collectOwned(input:DeliveryPlanningOptions,staging:boolean):Promi
249
253
  bindings,
250
254
  preparations,
251
255
  verification,
256
+ calldataReview: { record(tx, intent) {
257
+ if (callReviews.has(tx.transactionId)) throw Error('Duplicate calldata ABI intent');
258
+ callReviews.set(tx.transactionId, reviewTransaction(tx, createCalldataInvocation({ ...intent, data: tx.data })));
259
+ } },
252
260
  executionPlanner: planner,
253
261
  transactionIdentity: operationIds,
254
262
  transactionObserver: audit,
@@ -326,6 +334,12 @@ async function collectOwned(input:DeliveryPlanningOptions,staging:boolean):Promi
326
334
  derivedBindings = bindings.seal();
327
335
  const prepared = preparations.seal(transactions, derivedBindings),
328
336
  observations = verification.seal();
337
+ for (const review of await preparationCalldataReviews(prepared, transactions, context.runtime.hre.artifacts)) {
338
+ if (callReviews.has(review.transactionId)) throw Error('Duplicate calldata preparation intent');
339
+ callReviews.set(review.transactionId, review);
340
+ }
341
+ const calldata = parseCalldataReviews(transactions.map(tx => callReviews.get(tx.transactionId)), transactions);
342
+ if (input.expected?.calldata && canonicalJson(parseCalldataReviews(input.expected.calldata, transactions)) !== canonicalJson(calldata)) throw Error('Replayed calldata ABI intent differs');
329
343
  const {inputsHash:knownHash,...base}=header;
330
344
  const payload = deepFreeze({
331
345
  ...base,
@@ -359,7 +373,7 @@ async function collectOwned(input:DeliveryPlanningOptions,staging:boolean):Promi
359
373
  throw new Error("Replayed verification evidence differs");
360
374
  session?.closeReads();
361
375
  const interval=await audit.capture({transactions,completedTransactions:input.completedTransactions??[]});
362
- const stagedSnapshot=deepFreeze({payload,preparations:prepared,verification:observations,runtimeEvidence:{pendingUupsReuse:pendingObservations,forkAudit:interval.snapshot,references}});
376
+ const stagedSnapshot=deepFreeze({payload,calldata,preparations:prepared,verification:observations,runtimeEvidence:{pendingUupsReuse:pendingObservations,forkAudit:interval.snapshot,references}});
363
377
  const invariantHash=semanticHash(stagedSnapshot);
364
378
  let state:'staged'|'bound'|'failed'|'closed'='staged';
365
379
  const open=()=>{if(state!=='staged')throw new Error('Staged collection closed or already bound');};
@@ -368,7 +382,7 @@ async function collectOwned(input:DeliveryPlanningOptions,staging:boolean):Promi
368
382
  const plan=sealDeliveryPlan({...payload,inputsHash});
369
383
  if(expected&&plan.planHash!==expected.planHash)throw new Error('Replayed delivery plan differs from expected plan');
370
384
  const forkAudit=interval.bind(plan.planHash);
371
- const result=deepFreeze(canonicalData({plan,preparations:prepared,verification:observations,
385
+ const result=deepFreeze(canonicalData({plan,calldata,preparations:prepared,verification:observations,
372
386
  runtimeEvidence:{pendingUupsReuse:pendingObservations,forkAudit,references}}) as unknown as DeliveryCollection);
373
387
  if(collectionInvariantHash(result)!==invariantHash)throw new Error('Binding changed staged collection payload');
374
388
  state='bound';return result;
@@ -393,5 +407,5 @@ async function collectOwned(input:DeliveryPlanningOptions,staging:boolean):Promi
393
407
  export function collectionInvariantHash(collection:DeliveryCollection):string {
394
408
  const {inputsHash:_,planHash:__,...payload}=collection.plan;
395
409
  const {planHash:___,evidenceHash:____,...forkAudit}=collection.runtimeEvidence.forkAudit;
396
- return semanticHash({payload,preparations:collection.preparations,verification:collection.verification,runtimeEvidence:{...collection.runtimeEvidence,forkAudit}});
410
+ return semanticHash({payload,calldata:collection.calldata,preparations:collection.preparations,verification:collection.verification,runtimeEvidence:{...collection.runtimeEvidence,forkAudit}});
397
411
  }
@@ -2,6 +2,7 @@
2
2
  import { Interface, concat, getCreate2Address } from "ethers";
3
3
  import {
4
4
  artifactIdentity,
5
+ TRANSPARENT_PROXY_ARTIFACT, PROXY_ADMIN_ARTIFACT, PROXY_ADMIN_INTERFACE, transparentAdminAddress,
5
6
  type GateToolArtifact,
6
7
  type GateToolPreparationPlanV1,
7
8
  type GateToolPreparationRequestV1,
@@ -173,10 +174,24 @@ export async function validatePreparationSemantics(
173
174
  artifact,
174
175
  request.constructorArgs,
175
176
  request.implementationSalt,
176
- request.kind === "uups-upgrade"
177
+ (request.kind === "uups-upgrade" || request.kind === "transparent-upgrade")
177
178
  ? request.implementationAddressPolicy
178
179
  : undefined,
179
180
  );
181
+ if(request.kind === 'transparent-deploy' || request.kind === 'transparent-upgrade'){
182
+ if(request.call)validateAbiArguments(artifact.abi,request.call.method,request.call.args);
183
+ const data=request.call?new Interface(artifact.abi).encodeFunctionData(request.call.method,request.call.args):'0x';
184
+ await read(PROXY_ADMIN_ARTIFACT);
185
+ const proxy=request.kind==='transparent-deploy'
186
+ ?role('proxy',deliveryArtifact(await read(TRANSPARENT_PROXY_ARTIFACT)),[implementation,request.proxyAdminOwner,data],request.proxySalt,request.proxyAddressPolicy)
187
+ :request.proxy.toLowerCase();
188
+ const admin=transparentAdminAddress(proxy);
189
+ if(plan.proxyKind!=='transparent'||plan.proxyAdmin?.address!==admin||plan.proxyAdmin?.owner!==request.proxyAdminOwner.toLowerCase()
190
+ ||(request.kind==='transparent-upgrade'&&request.proxyAdmin.toLowerCase()!==admin))throw Error('Actual Transparent admin identity differs from preparation');
191
+ if(request.kind==='transparent-upgrade')transactions.push({id:'upgrade-proxy',purpose:'upgrade-proxy',to:admin,value:'0',operation:0,
192
+ data:PROXY_ADMIN_INTERFACE.encodeFunctionData('upgradeAndCall',[proxy,implementation,data]).toLowerCase()});
193
+ if(request.kind==='transparent-deploy'&&deployments.find(d=>d.role==='proxy')?.status==='reused'&&deployments.some(d=>d.status==='required'))throw Error('Invalid actual Transparent reuse roles');
194
+ } else {
180
195
  const proxy =
181
196
  request.kind === "uups-placeholder-deploy"
182
197
  ? role(
@@ -215,6 +230,7 @@ export async function validatePreparationSemantics(
215
230
  });
216
231
  else if (deployments.some((d) => d.status === "required"))
217
232
  throw new Error("Invalid actual UUPS reuse roles");
233
+ }
218
234
  }
219
235
  if (
220
236
  canonicalJson(deployments) !== canonicalJson(plan.deployments) ||
@@ -1,6 +1,7 @@
1
1
  /** Remove signing authority, retaining independent model/RPC API configuration. */
2
2
  export function productionChildEnvironment(input:NodeJS.ProcessEnv):NodeJS.ProcessEnv {
3
3
  const out={...input};
4
- for(const key of Object.keys(out))if(/(^|_)(PRIVATE_KEY|MNEMONIC|SEED_PHRASE)$/.test(key)||/^GATEFLOW_(OPERATOR_TOKEN|PRODUCTION_|MAC_SECURE_SIGNER_)/.test(key)||/^GATE_(CUSTODY|SIGNER)_/.test(key))delete out[key];
4
+ // Also discard the retired alias if it remains in a caller's environment; it is never a signer input.
5
+ for(const key of Object.keys(out))if(/(^|_)(PRIVATE_KEY|WALLET_CREDENTIAL|MNEMONIC|SEED_PHRASE)$/.test(key)||key==='CUSTODY_API_BASE_URL'||/^GATEFLOW_(OPERATOR_TOKEN|PRODUCTION_|MAC_SECURE_SIGNER_)/.test(key)||/^GATE_(CUSTODY|SIGNER)_/.test(key))delete out[key];
5
6
  return out;
6
7
  }