@0xsequence/catapult 1.1.0

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 (393) hide show
  1. package/.eslintrc.json +29 -0
  2. package/.github/workflows/ci.yml +181 -0
  3. package/CONCEPT.md +24 -0
  4. package/README.md +772 -0
  5. package/contracts/checked-call.huff +65 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +16 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/commands/common.d.ts +11 -0
  11. package/dist/commands/common.d.ts.map +1 -0
  12. package/dist/commands/common.js +73 -0
  13. package/dist/commands/common.js.map +1 -0
  14. package/dist/commands/dry.d.ts +3 -0
  15. package/dist/commands/dry.d.ts.map +1 -0
  16. package/dist/commands/dry.js +171 -0
  17. package/dist/commands/dry.js.map +1 -0
  18. package/dist/commands/etherscan.d.ts +3 -0
  19. package/dist/commands/etherscan.d.ts.map +1 -0
  20. package/dist/commands/etherscan.js +323 -0
  21. package/dist/commands/etherscan.js.map +1 -0
  22. package/dist/commands/index.d.ts +6 -0
  23. package/dist/commands/index.d.ts.map +1 -0
  24. package/dist/commands/index.js +22 -0
  25. package/dist/commands/index.js.map +1 -0
  26. package/dist/commands/list.d.ts +3 -0
  27. package/dist/commands/list.d.ts.map +1 -0
  28. package/dist/commands/list.js +259 -0
  29. package/dist/commands/list.js.map +1 -0
  30. package/dist/commands/run.d.ts +3 -0
  31. package/dist/commands/run.d.ts.map +1 -0
  32. package/dist/commands/run.js +96 -0
  33. package/dist/commands/run.js.map +1 -0
  34. package/dist/commands/utils.d.ts +3 -0
  35. package/dist/commands/utils.d.ts.map +1 -0
  36. package/dist/commands/utils.js +46 -0
  37. package/dist/commands/utils.js.map +1 -0
  38. package/dist/index.d.ts +4 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +58 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/lib/__tests__/deployer-events.spec.d.ts +2 -0
  43. package/dist/lib/__tests__/deployer-events.spec.d.ts.map +1 -0
  44. package/dist/lib/__tests__/deployer-events.spec.js +260 -0
  45. package/dist/lib/__tests__/deployer-events.spec.js.map +1 -0
  46. package/dist/lib/__tests__/deployer.spec.d.ts +2 -0
  47. package/dist/lib/__tests__/deployer.spec.d.ts.map +1 -0
  48. package/dist/lib/__tests__/deployer.spec.js +884 -0
  49. package/dist/lib/__tests__/deployer.spec.js.map +1 -0
  50. package/dist/lib/__tests__/network-utils.spec.d.ts +2 -0
  51. package/dist/lib/__tests__/network-utils.spec.d.ts.map +1 -0
  52. package/dist/lib/__tests__/network-utils.spec.js +140 -0
  53. package/dist/lib/__tests__/network-utils.spec.js.map +1 -0
  54. package/dist/lib/contracts/__tests__/repository.spec.d.ts +2 -0
  55. package/dist/lib/contracts/__tests__/repository.spec.d.ts.map +1 -0
  56. package/dist/lib/contracts/__tests__/repository.spec.js +321 -0
  57. package/dist/lib/contracts/__tests__/repository.spec.js.map +1 -0
  58. package/dist/lib/contracts/repository.d.ts +27 -0
  59. package/dist/lib/contracts/repository.d.ts.map +1 -0
  60. package/dist/lib/contracts/repository.js +241 -0
  61. package/dist/lib/contracts/repository.js.map +1 -0
  62. package/dist/lib/core/__tests__/engine.spec.d.ts +2 -0
  63. package/dist/lib/core/__tests__/engine.spec.d.ts.map +1 -0
  64. package/dist/lib/core/__tests__/engine.spec.js +1212 -0
  65. package/dist/lib/core/__tests__/engine.spec.js.map +1 -0
  66. package/dist/lib/core/__tests__/graph.spec.d.ts +2 -0
  67. package/dist/lib/core/__tests__/graph.spec.d.ts.map +1 -0
  68. package/dist/lib/core/__tests__/graph.spec.js +116 -0
  69. package/dist/lib/core/__tests__/graph.spec.js.map +1 -0
  70. package/dist/lib/core/__tests__/json-integration.spec.d.ts +2 -0
  71. package/dist/lib/core/__tests__/json-integration.spec.d.ts.map +1 -0
  72. package/dist/lib/core/__tests__/json-integration.spec.js +300 -0
  73. package/dist/lib/core/__tests__/json-integration.spec.js.map +1 -0
  74. package/dist/lib/core/__tests__/loader.spec.d.ts +2 -0
  75. package/dist/lib/core/__tests__/loader.spec.d.ts.map +1 -0
  76. package/dist/lib/core/__tests__/loader.spec.js +288 -0
  77. package/dist/lib/core/__tests__/loader.spec.js.map +1 -0
  78. package/dist/lib/core/__tests__/multi-platform-verification.spec.d.ts +2 -0
  79. package/dist/lib/core/__tests__/multi-platform-verification.spec.d.ts.map +1 -0
  80. package/dist/lib/core/__tests__/multi-platform-verification.spec.js +342 -0
  81. package/dist/lib/core/__tests__/multi-platform-verification.spec.js.map +1 -0
  82. package/dist/lib/core/__tests__/resolver.spec.d.ts +2 -0
  83. package/dist/lib/core/__tests__/resolver.spec.d.ts.map +1 -0
  84. package/dist/lib/core/__tests__/resolver.spec.js +1367 -0
  85. package/dist/lib/core/__tests__/resolver.spec.js.map +1 -0
  86. package/dist/lib/core/__tests__/static-action.spec.d.ts +2 -0
  87. package/dist/lib/core/__tests__/static-action.spec.d.ts.map +1 -0
  88. package/dist/lib/core/__tests__/static-action.spec.js +136 -0
  89. package/dist/lib/core/__tests__/static-action.spec.js.map +1 -0
  90. package/dist/lib/core/context.d.ts +29 -0
  91. package/dist/lib/core/context.d.ts.map +1 -0
  92. package/dist/lib/core/context.js +88 -0
  93. package/dist/lib/core/context.js.map +1 -0
  94. package/dist/lib/core/engine.d.ts +25 -0
  95. package/dist/lib/core/engine.d.ts.map +1 -0
  96. package/dist/lib/core/engine.js +1191 -0
  97. package/dist/lib/core/engine.js.map +1 -0
  98. package/dist/lib/core/graph.d.ts +18 -0
  99. package/dist/lib/core/graph.d.ts.map +1 -0
  100. package/dist/lib/core/graph.js +158 -0
  101. package/dist/lib/core/graph.js.map +1 -0
  102. package/dist/lib/core/loader.d.ts +25 -0
  103. package/dist/lib/core/loader.d.ts.map +1 -0
  104. package/dist/lib/core/loader.js +248 -0
  105. package/dist/lib/core/loader.js.map +1 -0
  106. package/dist/lib/core/resolver.d.ts +20 -0
  107. package/dist/lib/core/resolver.d.ts.map +1 -0
  108. package/dist/lib/core/resolver.js +307 -0
  109. package/dist/lib/core/resolver.js.map +1 -0
  110. package/dist/lib/deployer.d.ts +39 -0
  111. package/dist/lib/deployer.d.ts.map +1 -0
  112. package/dist/lib/deployer.js +533 -0
  113. package/dist/lib/deployer.js.map +1 -0
  114. package/dist/lib/events/__tests__/event-system.spec.d.ts +2 -0
  115. package/dist/lib/events/__tests__/event-system.spec.d.ts.map +1 -0
  116. package/dist/lib/events/__tests__/event-system.spec.js +256 -0
  117. package/dist/lib/events/__tests__/event-system.spec.js.map +1 -0
  118. package/dist/lib/events/cli-adapter.d.ts +13 -0
  119. package/dist/lib/events/cli-adapter.d.ts.map +1 -0
  120. package/dist/lib/events/cli-adapter.js +244 -0
  121. package/dist/lib/events/cli-adapter.js.map +1 -0
  122. package/dist/lib/events/emitter.d.ts +11 -0
  123. package/dist/lib/events/emitter.d.ts.map +1 -0
  124. package/dist/lib/events/emitter.js +29 -0
  125. package/dist/lib/events/emitter.js.map +1 -0
  126. package/dist/lib/events/index.d.ts +4 -0
  127. package/dist/lib/events/index.d.ts.map +1 -0
  128. package/dist/lib/events/index.js +20 -0
  129. package/dist/lib/events/index.js.map +1 -0
  130. package/dist/lib/events/types.d.ts +368 -0
  131. package/dist/lib/events/types.d.ts.map +1 -0
  132. package/dist/lib/events/types.js +3 -0
  133. package/dist/lib/events/types.js.map +1 -0
  134. package/dist/lib/index.d.ts +5 -0
  135. package/dist/lib/index.d.ts.map +1 -0
  136. package/dist/lib/index.js +44 -0
  137. package/dist/lib/index.js.map +1 -0
  138. package/dist/lib/network-loader.d.ts +3 -0
  139. package/dist/lib/network-loader.d.ts.map +1 -0
  140. package/dist/lib/network-loader.js +80 -0
  141. package/dist/lib/network-loader.js.map +1 -0
  142. package/dist/lib/network-match.d.ts +3 -0
  143. package/dist/lib/network-match.d.ts.map +1 -0
  144. package/dist/lib/network-match.js +62 -0
  145. package/dist/lib/network-match.js.map +1 -0
  146. package/dist/lib/network-utils.d.ts +4 -0
  147. package/dist/lib/network-utils.d.ts.map +1 -0
  148. package/dist/lib/network-utils.js +39 -0
  149. package/dist/lib/network-utils.js.map +1 -0
  150. package/dist/lib/parsers/__tests__/buildinfo.spec.d.ts +2 -0
  151. package/dist/lib/parsers/__tests__/buildinfo.spec.d.ts.map +1 -0
  152. package/dist/lib/parsers/__tests__/buildinfo.spec.js +132 -0
  153. package/dist/lib/parsers/__tests__/buildinfo.spec.js.map +1 -0
  154. package/dist/lib/parsers/__tests__/job.spec.d.ts +2 -0
  155. package/dist/lib/parsers/__tests__/job.spec.d.ts.map +1 -0
  156. package/dist/lib/parsers/__tests__/job.spec.js +318 -0
  157. package/dist/lib/parsers/__tests__/job.spec.js.map +1 -0
  158. package/dist/lib/parsers/__tests__/template.spec.d.ts +2 -0
  159. package/dist/lib/parsers/__tests__/template.spec.d.ts.map +1 -0
  160. package/dist/lib/parsers/__tests__/template.spec.js +126 -0
  161. package/dist/lib/parsers/__tests__/template.spec.js.map +1 -0
  162. package/dist/lib/parsers/artifact/__tests__/artifact.spec.d.ts +2 -0
  163. package/dist/lib/parsers/artifact/__tests__/artifact.spec.d.ts.map +1 -0
  164. package/dist/lib/parsers/artifact/__tests__/artifact.spec.js +128 -0
  165. package/dist/lib/parsers/artifact/__tests__/artifact.spec.js.map +1 -0
  166. package/dist/lib/parsers/artifact/foundry-1.2.d.ts +3 -0
  167. package/dist/lib/parsers/artifact/foundry-1.2.d.ts.map +1 -0
  168. package/dist/lib/parsers/artifact/foundry-1.2.js +82 -0
  169. package/dist/lib/parsers/artifact/foundry-1.2.js.map +1 -0
  170. package/dist/lib/parsers/artifact/index.d.ts +3 -0
  171. package/dist/lib/parsers/artifact/index.d.ts.map +1 -0
  172. package/dist/lib/parsers/artifact/index.js +17 -0
  173. package/dist/lib/parsers/artifact/index.js.map +1 -0
  174. package/dist/lib/parsers/artifact/types.d.ts +3 -0
  175. package/dist/lib/parsers/artifact/types.d.ts.map +1 -0
  176. package/dist/lib/parsers/artifact/types.js +3 -0
  177. package/dist/lib/parsers/artifact/types.js.map +1 -0
  178. package/dist/lib/parsers/buildinfo.d.ts +5 -0
  179. package/dist/lib/parsers/buildinfo.d.ts.map +1 -0
  180. package/dist/lib/parsers/buildinfo.js +85 -0
  181. package/dist/lib/parsers/buildinfo.js.map +1 -0
  182. package/dist/lib/parsers/constants.d.ts +4 -0
  183. package/dist/lib/parsers/constants.d.ts.map +1 -0
  184. package/dist/lib/parsers/constants.js +45 -0
  185. package/dist/lib/parsers/constants.js.map +1 -0
  186. package/dist/lib/parsers/index.d.ts +5 -0
  187. package/dist/lib/parsers/index.d.ts.map +1 -0
  188. package/dist/lib/parsers/index.js +21 -0
  189. package/dist/lib/parsers/index.js.map +1 -0
  190. package/dist/lib/parsers/job.d.ts +3 -0
  191. package/dist/lib/parsers/job.d.ts.map +1 -0
  192. package/dist/lib/parsers/job.js +74 -0
  193. package/dist/lib/parsers/job.js.map +1 -0
  194. package/dist/lib/parsers/template.d.ts +3 -0
  195. package/dist/lib/parsers/template.d.ts.map +1 -0
  196. package/dist/lib/parsers/template.js +91 -0
  197. package/dist/lib/parsers/template.js.map +1 -0
  198. package/dist/lib/std/templates/assured-deployment.yaml +45 -0
  199. package/dist/lib/std/templates/erc-2470.yaml +67 -0
  200. package/dist/lib/std/templates/min-balance.yaml +32 -0
  201. package/dist/lib/std/templates/nano-universal-deployer.yaml +59 -0
  202. package/dist/lib/std/templates/raw-erc-2470.yaml +59 -0
  203. package/dist/lib/std/templates/raw-nano-universal-deployer.yaml +51 -0
  204. package/dist/lib/std/templates/raw-sequence-universal-deployer-2.yaml +48 -0
  205. package/dist/lib/std/templates/sequence-universal-deployer-2.yaml +57 -0
  206. package/dist/lib/types/__tests__/json-request-action.spec.d.ts +2 -0
  207. package/dist/lib/types/__tests__/json-request-action.spec.d.ts.map +1 -0
  208. package/dist/lib/types/__tests__/json-request-action.spec.js +219 -0
  209. package/dist/lib/types/__tests__/json-request-action.spec.js.map +1 -0
  210. package/dist/lib/types/__tests__/read-json-value.spec.d.ts +2 -0
  211. package/dist/lib/types/__tests__/read-json-value.spec.d.ts.map +1 -0
  212. package/dist/lib/types/__tests__/read-json-value.spec.js +233 -0
  213. package/dist/lib/types/__tests__/read-json-value.spec.js.map +1 -0
  214. package/dist/lib/types/actions.d.ts +74 -0
  215. package/dist/lib/types/actions.d.ts.map +1 -0
  216. package/dist/lib/types/actions.js +18 -0
  217. package/dist/lib/types/actions.js.map +1 -0
  218. package/dist/lib/types/artifacts.d.ts +15 -0
  219. package/dist/lib/types/artifacts.d.ts.map +1 -0
  220. package/dist/lib/types/artifacts.js +3 -0
  221. package/dist/lib/types/artifacts.js.map +1 -0
  222. package/dist/lib/types/buildinfo.d.ts +112 -0
  223. package/dist/lib/types/buildinfo.d.ts.map +1 -0
  224. package/dist/lib/types/buildinfo.js +3 -0
  225. package/dist/lib/types/buildinfo.js.map +1 -0
  226. package/dist/lib/types/conditions.d.ts +17 -0
  227. package/dist/lib/types/conditions.d.ts.map +1 -0
  228. package/dist/lib/types/conditions.js +21 -0
  229. package/dist/lib/types/conditions.js.map +1 -0
  230. package/dist/lib/types/contracts.d.ts +14 -0
  231. package/dist/lib/types/contracts.d.ts.map +1 -0
  232. package/dist/lib/types/contracts.js +3 -0
  233. package/dist/lib/types/contracts.js.map +1 -0
  234. package/dist/lib/types/definitions.d.ts +51 -0
  235. package/dist/lib/types/definitions.d.ts.map +1 -0
  236. package/dist/lib/types/definitions.js +3 -0
  237. package/dist/lib/types/definitions.js.map +1 -0
  238. package/dist/lib/types/index.d.ts +9 -0
  239. package/dist/lib/types/index.d.ts.map +1 -0
  240. package/dist/lib/types/index.js +25 -0
  241. package/dist/lib/types/index.js.map +1 -0
  242. package/dist/lib/types/network.d.ts +9 -0
  243. package/dist/lib/types/network.d.ts.map +1 -0
  244. package/dist/lib/types/network.js +3 -0
  245. package/dist/lib/types/network.js.map +1 -0
  246. package/dist/lib/types/project.d.ts +5 -0
  247. package/dist/lib/types/project.d.ts.map +1 -0
  248. package/dist/lib/types/project.js +3 -0
  249. package/dist/lib/types/project.js.map +1 -0
  250. package/dist/lib/types/task.d.ts +9 -0
  251. package/dist/lib/types/task.d.ts.map +1 -0
  252. package/dist/lib/types/task.js +3 -0
  253. package/dist/lib/types/task.js.map +1 -0
  254. package/dist/lib/types/values.d.ts +78 -0
  255. package/dist/lib/types/values.d.ts.map +1 -0
  256. package/dist/lib/types/values.js +3 -0
  257. package/dist/lib/types/values.js.map +1 -0
  258. package/dist/lib/utils/validation.d.ts +5 -0
  259. package/dist/lib/utils/validation.d.ts.map +1 -0
  260. package/dist/lib/utils/validation.js +77 -0
  261. package/dist/lib/utils/validation.js.map +1 -0
  262. package/dist/lib/validation/contract-references.d.ts +12 -0
  263. package/dist/lib/validation/contract-references.d.ts.map +1 -0
  264. package/dist/lib/validation/contract-references.js +112 -0
  265. package/dist/lib/validation/contract-references.js.map +1 -0
  266. package/dist/lib/validation/index.d.ts +1 -0
  267. package/dist/lib/validation/index.d.ts.map +1 -0
  268. package/dist/lib/validation/index.js +2 -0
  269. package/dist/lib/validation/index.js.map +1 -0
  270. package/dist/lib/verification/__tests__/etherscan.spec.d.ts +2 -0
  271. package/dist/lib/verification/__tests__/etherscan.spec.d.ts.map +1 -0
  272. package/dist/lib/verification/__tests__/etherscan.spec.js +565 -0
  273. package/dist/lib/verification/__tests__/etherscan.spec.js.map +1 -0
  274. package/dist/lib/verification/__tests__/sourcify.spec.d.ts +2 -0
  275. package/dist/lib/verification/__tests__/sourcify.spec.d.ts.map +1 -0
  276. package/dist/lib/verification/__tests__/sourcify.spec.js +212 -0
  277. package/dist/lib/verification/__tests__/sourcify.spec.js.map +1 -0
  278. package/dist/lib/verification/etherscan.d.ts +56 -0
  279. package/dist/lib/verification/etherscan.d.ts.map +1 -0
  280. package/dist/lib/verification/etherscan.js +340 -0
  281. package/dist/lib/verification/etherscan.js.map +1 -0
  282. package/dist/lib/verification/sourcify.d.ts +12 -0
  283. package/dist/lib/verification/sourcify.d.ts.map +1 -0
  284. package/dist/lib/verification/sourcify.js +227 -0
  285. package/dist/lib/verification/sourcify.js.map +1 -0
  286. package/eslint.config.js +48 -0
  287. package/examples/jobs/guards-v1.yaml +17 -0
  288. package/examples/jobs/sequence-seq-0001-patch.yaml +59 -0
  289. package/examples/jobs/sequence-v1.yaml +59 -0
  290. package/examples/templates/sequence-factory-v1.yaml +56 -0
  291. package/jest.config.js +25 -0
  292. package/package.json +68 -0
  293. package/src/cli.ts +17 -0
  294. package/src/commands/common.ts +61 -0
  295. package/src/commands/dry.ts +208 -0
  296. package/src/commands/etherscan.ts +360 -0
  297. package/src/commands/index.ts +5 -0
  298. package/src/commands/list.ts +249 -0
  299. package/src/commands/run.ts +136 -0
  300. package/src/commands/utils.ts +52 -0
  301. package/src/index.ts +67 -0
  302. package/src/lib/__tests__/deployer-events.spec.ts +338 -0
  303. package/src/lib/__tests__/deployer.spec.ts +1204 -0
  304. package/src/lib/__tests__/network-utils.spec.ts +181 -0
  305. package/src/lib/artifacts/__tests__/fixtures/contract1.json +19 -0
  306. package/src/lib/artifacts/__tests__/fixtures/contract2.json +19 -0
  307. package/src/lib/artifacts/__tests__/fixtures/duplicate-name.json +19 -0
  308. package/src/lib/artifacts/__tests__/fixtures/nested/nested-contract.json +18 -0
  309. package/src/lib/artifacts/__tests__/fixtures/not-an-artifact.json +8 -0
  310. package/src/lib/artifacts/__tests__/fixtures/readme.txt +2 -0
  311. package/src/lib/contracts/__tests__/repository.spec.ts +344 -0
  312. package/src/lib/contracts/repository.ts +313 -0
  313. package/src/lib/core/__tests__/engine.spec.ts +1514 -0
  314. package/src/lib/core/__tests__/graph.spec.ts +125 -0
  315. package/src/lib/core/__tests__/json-integration.spec.ts +360 -0
  316. package/src/lib/core/__tests__/loader.spec.ts +334 -0
  317. package/src/lib/core/__tests__/multi-platform-verification.spec.ts +406 -0
  318. package/src/lib/core/__tests__/resolver.spec.ts +1693 -0
  319. package/src/lib/core/__tests__/static-action.spec.ts +172 -0
  320. package/src/lib/core/context.ts +127 -0
  321. package/src/lib/core/engine.ts +1531 -0
  322. package/src/lib/core/graph.ts +252 -0
  323. package/src/lib/core/loader.ts +263 -0
  324. package/src/lib/core/resolver.ts +498 -0
  325. package/src/lib/deployer.ts +768 -0
  326. package/src/lib/events/__tests__/event-system.spec.ts +343 -0
  327. package/src/lib/events/cli-adapter.ts +325 -0
  328. package/src/lib/events/emitter.ts +62 -0
  329. package/src/lib/events/index.ts +3 -0
  330. package/src/lib/events/types.ts +469 -0
  331. package/src/lib/index.ts +14 -0
  332. package/src/lib/network-loader.ts +59 -0
  333. package/src/lib/network-utils.ts +64 -0
  334. package/src/lib/parsers/__tests__/buildinfo.spec.ts +122 -0
  335. package/src/lib/parsers/__tests__/fixtures/buildinfo/invalid-bytecode-buildinfo.json +62 -0
  336. package/src/lib/parsers/__tests__/fixtures/buildinfo/invalid-json.txt +2 -0
  337. package/src/lib/parsers/__tests__/fixtures/buildinfo/multi-contract-buildinfo.json +89 -0
  338. package/src/lib/parsers/__tests__/fixtures/buildinfo/no-contracts-buildinfo.json +17 -0
  339. package/src/lib/parsers/__tests__/fixtures/buildinfo/simple-buildinfo.json +63 -0
  340. package/src/lib/parsers/__tests__/fixtures/buildinfo/wrong-format.json +4 -0
  341. package/src/lib/parsers/__tests__/job.spec.ts +335 -0
  342. package/src/lib/parsers/__tests__/template.spec.ts +111 -0
  343. package/src/lib/parsers/artifact/__tests__/artifact.spec.ts +117 -0
  344. package/src/lib/parsers/artifact/__tests__/fixtures/empty-bytecode.json +5 -0
  345. package/src/lib/parsers/artifact/__tests__/fixtures/hardhat-artifact.json +67 -0
  346. package/src/lib/parsers/artifact/__tests__/fixtures/invalid-bytecode.json +5 -0
  347. package/src/lib/parsers/artifact/__tests__/fixtures/invalid-json.txt +11 -0
  348. package/src/lib/parsers/artifact/__tests__/fixtures/minimal-artifact.json +5 -0
  349. package/src/lib/parsers/artifact/__tests__/fixtures/missing-abi.json +4 -0
  350. package/src/lib/parsers/artifact/__tests__/fixtures/missing-bytecode.json +11 -0
  351. package/src/lib/parsers/artifact/__tests__/fixtures/missing-contract-name.json +11 -0
  352. package/src/lib/parsers/artifact/__tests__/fixtures/simple-artifact.json +40 -0
  353. package/src/lib/parsers/artifact/__tests__/fixtures/wrong-types.json +7 -0
  354. package/src/lib/parsers/artifact/foundry-1.2.ts +72 -0
  355. package/src/lib/parsers/artifact/index.ts +27 -0
  356. package/src/lib/parsers/artifact/types.ts +9 -0
  357. package/src/lib/parsers/buildinfo.ts +127 -0
  358. package/src/lib/parsers/constants.ts +56 -0
  359. package/src/lib/parsers/index.ts +5 -0
  360. package/src/lib/parsers/job.ts +101 -0
  361. package/src/lib/parsers/template.ts +131 -0
  362. package/src/lib/std/templates/assured-deployment.yaml +45 -0
  363. package/src/lib/std/templates/erc-2470.yaml +67 -0
  364. package/src/lib/std/templates/min-balance.yaml +32 -0
  365. package/src/lib/std/templates/nano-universal-deployer.yaml +59 -0
  366. package/src/lib/std/templates/raw-erc-2470.yaml +59 -0
  367. package/src/lib/std/templates/raw-nano-universal-deployer.yaml +51 -0
  368. package/src/lib/std/templates/raw-sequence-universal-deployer-2.yaml +48 -0
  369. package/src/lib/std/templates/sequence-universal-deployer-2.yaml +57 -0
  370. package/src/lib/types/__tests__/json-request-action.spec.ts +243 -0
  371. package/src/lib/types/__tests__/read-json-value.spec.ts +264 -0
  372. package/src/lib/types/actions.ts +127 -0
  373. package/src/lib/types/artifacts.ts +21 -0
  374. package/src/lib/types/buildinfo.ts +116 -0
  375. package/src/lib/types/conditions.ts +50 -0
  376. package/src/lib/types/contracts.ts +23 -0
  377. package/src/lib/types/definitions.ts +68 -0
  378. package/src/lib/types/index.ts +8 -0
  379. package/src/lib/types/network.ts +22 -0
  380. package/src/lib/types/project.ts +9 -0
  381. package/src/lib/types/task.ts +9 -0
  382. package/src/lib/types/values.ts +116 -0
  383. package/src/lib/utils/validation.ts +116 -0
  384. package/src/lib/validation/contract-references.ts +210 -0
  385. package/src/lib/validation/index.ts +1 -0
  386. package/src/lib/verification/__tests__/etherscan.spec.ts +710 -0
  387. package/src/lib/verification/__tests__/sourcify.spec.ts +288 -0
  388. package/src/lib/verification/etherscan.ts +546 -0
  389. package/src/lib/verification/sourcify.ts +248 -0
  390. package/test_validation/artifacts/TestContract.json +9 -0
  391. package/test_validation/jobs/test-missing.yaml +16 -0
  392. package/test_validation/networks.yaml +3 -0
  393. package/tsconfig.json +36 -0
@@ -0,0 +1,1367 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const ethers_1 = require("ethers");
4
+ const resolver_1 = require("../resolver");
5
+ const context_1 = require("../context");
6
+ const repository_1 = require("../../contracts/repository");
7
+ describe('ValueResolver', () => {
8
+ let resolver;
9
+ let context;
10
+ let mockNetwork;
11
+ let mockRegistry;
12
+ beforeEach(async () => {
13
+ resolver = new resolver_1.ValueResolver();
14
+ mockRegistry = new repository_1.ContractRepository();
15
+ const rpcUrl = process.env.RPC_URL || 'http://127.0.0.1:8545';
16
+ mockNetwork = { name: 'testnet', chainId: 999, rpcUrl };
17
+ const mockPrivateKey = '0x0000000000000000000000000000000000000000000000000000000000000001';
18
+ context = new context_1.ExecutionContext(mockNetwork, mockPrivateKey, mockRegistry);
19
+ await context.provider.getNetwork();
20
+ });
21
+ afterEach(async () => {
22
+ if (context) {
23
+ try {
24
+ await context.dispose();
25
+ }
26
+ catch (error) {
27
+ }
28
+ }
29
+ });
30
+ describe('basic-arithmetic', () => {
31
+ it('should add two numbers', async () => {
32
+ const value = {
33
+ type: 'basic-arithmetic',
34
+ arguments: { operation: 'add', values: ["100", "50"] },
35
+ };
36
+ const result = await resolver.resolve(value, context);
37
+ expect(result).toBe('150');
38
+ });
39
+ it('should subtract two numbers', async () => {
40
+ const value = {
41
+ type: 'basic-arithmetic',
42
+ arguments: { operation: 'sub', values: [100, 50] },
43
+ };
44
+ const result = await resolver.resolve(value, context);
45
+ expect(result).toBe('50');
46
+ });
47
+ it('should multiply two numbers', async () => {
48
+ const value = {
49
+ type: 'basic-arithmetic',
50
+ arguments: { operation: 'mul', values: [10, 5] },
51
+ };
52
+ const result = await resolver.resolve(value, context);
53
+ expect(result).toBe('50');
54
+ });
55
+ it('should divide two numbers (integer division)', async () => {
56
+ const value = {
57
+ type: 'basic-arithmetic',
58
+ arguments: { operation: 'div', values: [10, 3] },
59
+ };
60
+ const result = await resolver.resolve(value, context);
61
+ expect(result).toBe('3');
62
+ });
63
+ it('should handle large numbers as strings', async () => {
64
+ const value = {
65
+ type: 'basic-arithmetic',
66
+ arguments: { operation: 'add', values: ['10000000000000000000', '5000000000000000000'] },
67
+ };
68
+ const result = await resolver.resolve(value, context);
69
+ expect(result).toBe('15000000000000000000');
70
+ });
71
+ it('should correctly evaluate "eq" (equal)', async () => {
72
+ const valueTrue = { type: 'basic-arithmetic', arguments: { operation: 'eq', values: [10, 10] } };
73
+ const valueFalse = { type: 'basic-arithmetic', arguments: { operation: 'eq', values: [10, 5] } };
74
+ expect(await resolver.resolve(valueTrue, context)).toBe(true);
75
+ expect(await resolver.resolve(valueFalse, context)).toBe(false);
76
+ });
77
+ it('should correctly evaluate "neq" (not equal)', async () => {
78
+ const valueTrue = { type: 'basic-arithmetic', arguments: { operation: 'neq', values: [10, 5] } };
79
+ const valueFalse = { type: 'basic-arithmetic', arguments: { operation: 'neq', values: [10, 10] } };
80
+ expect(await resolver.resolve(valueTrue, context)).toBe(true);
81
+ expect(await resolver.resolve(valueFalse, context)).toBe(false);
82
+ });
83
+ it('should correctly evaluate "gt" (greater than)', async () => {
84
+ const valueTrue = { type: 'basic-arithmetic', arguments: { operation: 'gt', values: [10, 5] } };
85
+ const valueFalse = { type: 'basic-arithmetic', arguments: { operation: 'gt', values: [10, 10] } };
86
+ expect(await resolver.resolve(valueTrue, context)).toBe(true);
87
+ expect(await resolver.resolve(valueFalse, context)).toBe(false);
88
+ });
89
+ it('should correctly evaluate "gte" (greater than or equal)', async () => {
90
+ const valueTrue1 = { type: 'basic-arithmetic', arguments: { operation: 'gte', values: [10, 5] } };
91
+ const valueTrue2 = { type: 'basic-arithmetic', arguments: { operation: 'gte', values: [10, 10] } };
92
+ const valueFalse = { type: 'basic-arithmetic', arguments: { operation: 'gte', values: [5, 10] } };
93
+ expect(await resolver.resolve(valueTrue1, context)).toBe(true);
94
+ expect(await resolver.resolve(valueTrue2, context)).toBe(true);
95
+ expect(await resolver.resolve(valueFalse, context)).toBe(false);
96
+ });
97
+ it('should correctly evaluate "lt" (less than)', async () => {
98
+ const valueTrue = { type: 'basic-arithmetic', arguments: { operation: 'lt', values: [5, 10] } };
99
+ const valueFalse = { type: 'basic-arithmetic', arguments: { operation: 'lt', values: [10, 10] } };
100
+ expect(await resolver.resolve(valueTrue, context)).toBe(true);
101
+ expect(await resolver.resolve(valueFalse, context)).toBe(false);
102
+ });
103
+ it('should correctly evaluate "lte" (less than or equal)', async () => {
104
+ const valueTrue1 = { type: 'basic-arithmetic', arguments: { operation: 'lte', values: [5, 10] } };
105
+ const valueTrue2 = { type: 'basic-arithmetic', arguments: { operation: 'lte', values: [10, 10] } };
106
+ const valueFalse = { type: 'basic-arithmetic', arguments: { operation: 'lte', values: [10, 5] } };
107
+ expect(await resolver.resolve(valueTrue1, context)).toBe(true);
108
+ expect(await resolver.resolve(valueTrue2, context)).toBe(true);
109
+ expect(await resolver.resolve(valueFalse, context)).toBe(false);
110
+ });
111
+ it('should resolve nested values before performing the operation', async () => {
112
+ context.setOutput('fee', '10000000000000000');
113
+ const value = {
114
+ type: 'basic-arithmetic',
115
+ arguments: { operation: 'add', values: ['{{fee}}', '5000000000000000'] },
116
+ };
117
+ const result = await resolver.resolve(value, context);
118
+ expect(result).toBe('15000000000000000');
119
+ });
120
+ });
121
+ describe('read-balance', () => {
122
+ const testAddress = '0x1234567890123456789012345678901234567890';
123
+ const testAddress2 = '0x0987654321098765432109876543210987654321';
124
+ let anvilProvider;
125
+ beforeEach(async () => {
126
+ anvilProvider = context.provider;
127
+ await anvilProvider.send('anvil_setBalance', [testAddress, '0x0']);
128
+ await anvilProvider.send('anvil_setBalance', [testAddress2, '0x0']);
129
+ });
130
+ it('should read balance for an address with 0 ETH', async () => {
131
+ const value = {
132
+ type: 'read-balance',
133
+ arguments: { address: testAddress },
134
+ };
135
+ const result = await resolver.resolve(value, context);
136
+ expect(result).toBe('0');
137
+ });
138
+ it('should read balance for an address with 1 ETH', async () => {
139
+ await anvilProvider.send('anvil_setBalance', [testAddress, '0xde0b6b3a7640000']);
140
+ const value = {
141
+ type: 'read-balance',
142
+ arguments: { address: testAddress },
143
+ };
144
+ const result = await resolver.resolve(value, context);
145
+ expect(result).toBe('1000000000000000000');
146
+ });
147
+ it('should read balance for an address with 100 ETH', async () => {
148
+ await anvilProvider.send('anvil_setBalance', [testAddress, '0x56bc75e2d63100000']);
149
+ const value = {
150
+ type: 'read-balance',
151
+ arguments: { address: testAddress },
152
+ };
153
+ const result = await resolver.resolve(value, context);
154
+ expect(result).toBe('100000000000000000000');
155
+ });
156
+ it('should read balance for an address with custom amount', async () => {
157
+ await anvilProvider.send('anvil_setBalance', [testAddress, '0xab524017e8328000']);
158
+ const value = {
159
+ type: 'read-balance',
160
+ arguments: { address: testAddress },
161
+ };
162
+ const result = await resolver.resolve(value, context);
163
+ expect(result).toBe('12345000000000000000');
164
+ });
165
+ it('should read different balances for different addresses', async () => {
166
+ await anvilProvider.send('anvil_setBalance', [testAddress, '0xde0b6b3a7640000']);
167
+ await anvilProvider.send('anvil_setBalance', [testAddress2, '0x1bc16d674ec80000']);
168
+ const value1 = {
169
+ type: 'read-balance',
170
+ arguments: { address: testAddress },
171
+ };
172
+ const value2 = {
173
+ type: 'read-balance',
174
+ arguments: { address: testAddress2 },
175
+ };
176
+ const result1 = await resolver.resolve(value1, context);
177
+ const result2 = await resolver.resolve(value2, context);
178
+ expect(result1).toBe('1000000000000000000');
179
+ expect(result2).toBe('2000000000000000000');
180
+ });
181
+ it('should resolve address from context variable', async () => {
182
+ context.setOutput('myAddress', testAddress);
183
+ await anvilProvider.send('anvil_setBalance', [testAddress, '0xde0b6b3a7640000']);
184
+ const value = {
185
+ type: 'read-balance',
186
+ arguments: { address: '{{myAddress}}' },
187
+ };
188
+ const result = await resolver.resolve(value, context);
189
+ expect(result).toBe('1000000000000000000');
190
+ });
191
+ it('should throw error for invalid address', async () => {
192
+ const value = {
193
+ type: 'read-balance',
194
+ arguments: { address: 'invalid-address' },
195
+ };
196
+ await expect(resolver.resolve(value, context)).rejects.toThrow('Invalid address: invalid-address');
197
+ });
198
+ it('should throw error for null address', async () => {
199
+ const value = {
200
+ type: 'read-balance',
201
+ arguments: { address: null },
202
+ };
203
+ await expect(resolver.resolve(value, context)).rejects.toThrow('Invalid address: null');
204
+ });
205
+ it('should throw error for undefined address', async () => {
206
+ const value = {
207
+ type: 'read-balance',
208
+ arguments: { address: undefined },
209
+ };
210
+ await expect(resolver.resolve(value, context)).rejects.toThrow('Invalid address: undefined');
211
+ });
212
+ it('should handle very large balance amounts', async () => {
213
+ await anvilProvider.send('anvil_setBalance', [testAddress, '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff']);
214
+ const value = {
215
+ type: 'read-balance',
216
+ arguments: { address: testAddress },
217
+ };
218
+ const result = await resolver.resolve(value, context);
219
+ expect(result).toBe('115792089237316195423570985008687907853269984665640564039457584007913129639935');
220
+ });
221
+ it('should handle checksummed addresses', async () => {
222
+ const checksummedAddress = '0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed';
223
+ await anvilProvider.send('anvil_setBalance', [checksummedAddress, '0xde0b6b3a7640000']);
224
+ const value = {
225
+ type: 'read-balance',
226
+ arguments: { address: checksummedAddress },
227
+ };
228
+ const result = await resolver.resolve(value, context);
229
+ expect(result).toBe('1000000000000000000');
230
+ });
231
+ it('should handle lowercase addresses', async () => {
232
+ const lowercaseAddress = testAddress.toLowerCase();
233
+ await anvilProvider.send('anvil_setBalance', [lowercaseAddress, '0xde0b6b3a7640000']);
234
+ const value = {
235
+ type: 'read-balance',
236
+ arguments: { address: lowercaseAddress },
237
+ };
238
+ const result = await resolver.resolve(value, context);
239
+ expect(result).toBe('1000000000000000000');
240
+ });
241
+ });
242
+ describe('compute-create2', () => {
243
+ it('should compute CREATE2 address with hardcoded test case 1', async () => {
244
+ const value = {
245
+ type: 'compute-create2',
246
+ arguments: {
247
+ deployerAddress: '0x0000000000000000000000000000000000000000',
248
+ salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
249
+ initCode: '0x00',
250
+ },
251
+ };
252
+ const result = await resolver.resolve(value, context);
253
+ expect(result).toBe('0x4D1A2e2bB4F88F0250f26Ffff098B0b30B26BF38');
254
+ });
255
+ it('should compute CREATE2 address with hardcoded test case 2', async () => {
256
+ const value = {
257
+ type: 'compute-create2',
258
+ arguments: {
259
+ deployerAddress: '0xdeadbeef00000000000000000000000000000000',
260
+ salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
261
+ initCode: '0x00',
262
+ },
263
+ };
264
+ const result = await resolver.resolve(value, context);
265
+ expect(result).toBe('0xB928f69Bb1D91Cd65274e3c79d8986362984fDA3');
266
+ });
267
+ it('should compute CREATE2 address with hardcoded test case 3', async () => {
268
+ const value = {
269
+ type: 'compute-create2',
270
+ arguments: {
271
+ deployerAddress: '0xdeadbeef00000000000000000000000000000000',
272
+ salt: '0x000000000000000000000000feed000000000000000000000000000000000000',
273
+ initCode: '0x00',
274
+ },
275
+ };
276
+ const result = await resolver.resolve(value, context);
277
+ expect(result).toBe('0xD04116cDd17beBE565EB2422F2497E06cC1C9833');
278
+ });
279
+ it('should compute CREATE2 address with hardcoded test case 4', async () => {
280
+ const value = {
281
+ type: 'compute-create2',
282
+ arguments: {
283
+ deployerAddress: '0x0000000000000000000000000000000000000000',
284
+ salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
285
+ initCode: '0xdeadbeef',
286
+ },
287
+ };
288
+ const result = await resolver.resolve(value, context);
289
+ expect(result).toBe('0x70f2b2914A2a4b783FaEFb75f459A580616Fcb5e');
290
+ });
291
+ it('should compute CREATE2 address with hardcoded test case 5', async () => {
292
+ const value = {
293
+ type: 'compute-create2',
294
+ arguments: {
295
+ deployerAddress: '0x00000000000000000000000000000000deadbeef',
296
+ salt: '0x00000000000000000000000000000000000000000000000000000000cafebabe',
297
+ initCode: '0xdeadbeef',
298
+ },
299
+ };
300
+ const result = await resolver.resolve(value, context);
301
+ expect(result).toBe('0x60f3f640a8508fC6a86d45DF051962668E1e8AC7');
302
+ });
303
+ it('should compute CREATE2 address with hardcoded test case 6', async () => {
304
+ const value = {
305
+ type: 'compute-create2',
306
+ arguments: {
307
+ deployerAddress: '0x00000000000000000000000000000000deadbeef',
308
+ salt: '0x00000000000000000000000000000000000000000000000000000000cafebabe',
309
+ initCode: '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef',
310
+ },
311
+ };
312
+ const result = await resolver.resolve(value, context);
313
+ expect(result).toBe('0x1d8bfDC5D46DC4f61D6b6115972536eBE6A8854C');
314
+ });
315
+ it('should compute CREATE2 address with hardcoded test case 7 (empty initCode)', async () => {
316
+ const value = {
317
+ type: 'compute-create2',
318
+ arguments: {
319
+ deployerAddress: '0x0000000000000000000000000000000000000000',
320
+ salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
321
+ initCode: '0x',
322
+ },
323
+ };
324
+ const result = await resolver.resolve(value, context);
325
+ expect(result).toBe('0xE33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0');
326
+ });
327
+ it('should resolve values from context before computing CREATE2 address', async () => {
328
+ context.setOutput('myDeployer', '0x0000000000000000000000000000000000000000');
329
+ context.setOutput('mySalt', '0x0000000000000000000000000000000000000000000000000000000000000000');
330
+ context.setOutput('myInitCode', '0x00');
331
+ const value = {
332
+ type: 'compute-create2',
333
+ arguments: {
334
+ deployerAddress: '{{myDeployer}}',
335
+ salt: '{{mySalt}}',
336
+ initCode: '{{myInitCode}}',
337
+ },
338
+ };
339
+ const result = await resolver.resolve(value, context);
340
+ expect(result).toBe('0x4D1A2e2bB4F88F0250f26Ffff098B0b30B26BF38');
341
+ });
342
+ it('should throw error for invalid deployer address', async () => {
343
+ const value = {
344
+ type: 'compute-create2',
345
+ arguments: {
346
+ deployerAddress: 'invalid-address',
347
+ salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
348
+ initCode: '0x00',
349
+ },
350
+ };
351
+ await expect(resolver.resolve(value, context)).rejects.toThrow('Invalid deployer address: invalid-address');
352
+ });
353
+ it('should throw error for invalid salt', async () => {
354
+ const value = {
355
+ type: 'compute-create2',
356
+ arguments: {
357
+ deployerAddress: '0x0000000000000000000000000000000000000000',
358
+ salt: 'invalid-salt',
359
+ initCode: '0x00',
360
+ },
361
+ };
362
+ await expect(resolver.resolve(value, context)).rejects.toThrow('Invalid salt: invalid-salt');
363
+ });
364
+ it('should throw error for invalid init code', async () => {
365
+ const value = {
366
+ type: 'compute-create2',
367
+ arguments: {
368
+ deployerAddress: '0x0000000000000000000000000000000000000000',
369
+ salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
370
+ initCode: 'invalid-init-code',
371
+ },
372
+ };
373
+ await expect(resolver.resolve(value, context)).rejects.toThrow('Invalid init code: invalid-init-code');
374
+ });
375
+ it('should throw error for null deployer address', async () => {
376
+ const value = {
377
+ type: 'compute-create2',
378
+ arguments: {
379
+ deployerAddress: null,
380
+ salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
381
+ initCode: '0x00',
382
+ },
383
+ };
384
+ await expect(resolver.resolve(value, context)).rejects.toThrow('Invalid deployer address: null');
385
+ });
386
+ it('should throw error for undefined salt', async () => {
387
+ const value = {
388
+ type: 'compute-create2',
389
+ arguments: {
390
+ deployerAddress: '0x0000000000000000000000000000000000000000',
391
+ salt: undefined,
392
+ initCode: '0x00',
393
+ },
394
+ };
395
+ await expect(resolver.resolve(value, context)).rejects.toThrow('Invalid salt: undefined');
396
+ });
397
+ it('should handle checksummed addresses', async () => {
398
+ const value = {
399
+ type: 'compute-create2',
400
+ arguments: {
401
+ deployerAddress: '0xdEADBEeF00000000000000000000000000000000',
402
+ salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
403
+ initCode: '0x00',
404
+ },
405
+ };
406
+ const result = await resolver.resolve(value, context);
407
+ expect(result).toBe('0xB928f69Bb1D91Cd65274e3c79d8986362984fDA3');
408
+ });
409
+ it('should handle uppercase hex strings', async () => {
410
+ const value = {
411
+ type: 'compute-create2',
412
+ arguments: {
413
+ deployerAddress: '0x0000000000000000000000000000000000000000',
414
+ salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
415
+ initCode: '0xDEADBEEF',
416
+ },
417
+ };
418
+ const result = await resolver.resolve(value, context);
419
+ expect(result).toBe('0x70f2b2914A2a4b783FaEFb75f459A580616Fcb5e');
420
+ });
421
+ });
422
+ describe('constructor-encode', () => {
423
+ it('should encode creation code with no constructor arguments', async () => {
424
+ const value = {
425
+ type: 'constructor-encode',
426
+ arguments: {
427
+ creationCode: '0x608060405234801561001057600080fd5b50',
428
+ types: [],
429
+ values: []
430
+ }
431
+ };
432
+ const result = await resolver.resolve(value, context);
433
+ expect(result).toBe('0x608060405234801561001057600080fd5b50');
434
+ });
435
+ it('should encode creation code with a single address argument', async () => {
436
+ const value = {
437
+ type: 'constructor-encode',
438
+ arguments: {
439
+ creationCode: '0x608060405234801561001057600080fd5b50',
440
+ types: ['address'],
441
+ values: ['0x1234567890123456789012345678901234567890']
442
+ }
443
+ };
444
+ const result = await resolver.resolve(value, context);
445
+ expect(result).toBe('0x608060405234801561001057600080fd5b500000000000000000000000001234567890123456789012345678901234567890');
446
+ });
447
+ it('should encode creation code with multiple arguments', async () => {
448
+ const value = {
449
+ type: 'constructor-encode',
450
+ arguments: {
451
+ creationCode: '0x608060405234801561001057600080fd5b50',
452
+ types: ['address', 'uint256'],
453
+ values: ['0x1234567890123456789012345678901234567890', '42']
454
+ }
455
+ };
456
+ const result = await resolver.resolve(value, context);
457
+ expect(result.startsWith('0x608060405234801561001057600080fd5b50')).toBe(true);
458
+ expect(result.length).toBeGreaterThan('0x608060405234801561001057600080fd5b50'.length);
459
+ });
460
+ it('should validate that types and values arrays have same length', async () => {
461
+ const value = {
462
+ type: 'constructor-encode',
463
+ arguments: {
464
+ creationCode: '0x608060405234801561001057600080fd5b50',
465
+ types: ['address'],
466
+ values: ['0x1234567890123456789012345678901234567890', '42']
467
+ }
468
+ };
469
+ await expect(resolver.resolve(value, context)).rejects.toThrow('constructor-encode: types array length (1) must match values array length (2)');
470
+ });
471
+ it('should validate creation code is valid bytecode', async () => {
472
+ const value = {
473
+ type: 'constructor-encode',
474
+ arguments: {
475
+ creationCode: 'not-valid-bytecode',
476
+ types: [],
477
+ values: []
478
+ }
479
+ };
480
+ await expect(resolver.resolve(value, context)).rejects.toThrow('Invalid creation code: not-valid-bytecode');
481
+ });
482
+ it('should encode just constructor arguments when no creationCode provided', async () => {
483
+ const value = {
484
+ type: 'constructor-encode',
485
+ arguments: {
486
+ types: ['address'],
487
+ values: ['0x1234567890123456789012345678901234567890']
488
+ }
489
+ };
490
+ const result = await resolver.resolve(value, context);
491
+ expect(result).toBe('0x0000000000000000000000001234567890123456789012345678901234567890');
492
+ });
493
+ it('should encode multiple constructor arguments when no creationCode provided', async () => {
494
+ const value = {
495
+ type: 'constructor-encode',
496
+ arguments: {
497
+ types: ['address', 'uint256'],
498
+ values: ['0x1234567890123456789012345678901234567890', '42']
499
+ }
500
+ };
501
+ const result = await resolver.resolve(value, context);
502
+ expect(result.startsWith('0x')).toBe(true);
503
+ expect(result).toBe('0x0000000000000000000000001234567890123456789012345678901234567890000000000000000000000000000000000000000000000000000000000000002a');
504
+ });
505
+ it('should return 0x when no creationCode and no constructor arguments', async () => {
506
+ const value = {
507
+ type: 'constructor-encode',
508
+ arguments: {
509
+ types: [],
510
+ values: []
511
+ }
512
+ };
513
+ const result = await resolver.resolve(value, context);
514
+ expect(result).toBe('0x');
515
+ });
516
+ it('should validate that types and values arrays have same length when no creationCode', async () => {
517
+ const value = {
518
+ type: 'constructor-encode',
519
+ arguments: {
520
+ types: ['address'],
521
+ values: ['0x1234567890123456789012345678901234567890', '42']
522
+ }
523
+ };
524
+ await expect(resolver.resolve(value, context)).rejects.toThrow('constructor-encode: types array length (1) must match values array length (2)');
525
+ });
526
+ });
527
+ describe('abi-encode', () => {
528
+ it('should encode a simple function with no parameters', async () => {
529
+ const value = {
530
+ type: 'abi-encode',
531
+ arguments: {
532
+ signature: 'withdraw()',
533
+ values: []
534
+ }
535
+ };
536
+ const result = await resolver.resolve(value, context);
537
+ expect(result).toBe('0x3ccfd60b');
538
+ });
539
+ it('should encode a function with a single address parameter', async () => {
540
+ const value = {
541
+ type: 'abi-encode',
542
+ arguments: {
543
+ signature: 'transfer(address)',
544
+ values: ['0x1234567890123456789012345678901234567890']
545
+ }
546
+ };
547
+ const result = await resolver.resolve(value, context);
548
+ expect(result.startsWith('0x1a695230')).toBe(true);
549
+ expect(result.length).toBe(74);
550
+ });
551
+ it('should encode a function with multiple parameters', async () => {
552
+ const value = {
553
+ type: 'abi-encode',
554
+ arguments: {
555
+ signature: 'transfer(address,uint256)',
556
+ values: ['0x1234567890123456789012345678901234567890', '1000000000000000000']
557
+ }
558
+ };
559
+ const result = await resolver.resolve(value, context);
560
+ expect(result.startsWith('0xa9059cbb')).toBe(true);
561
+ expect(result.length).toBe(138);
562
+ });
563
+ it('should encode a function with various parameter types', async () => {
564
+ const value = {
565
+ type: 'abi-encode',
566
+ arguments: {
567
+ signature: 'complexFunction(address,uint256,bool,string)',
568
+ values: [
569
+ '0x1234567890123456789012345678901234567890',
570
+ '42',
571
+ true,
572
+ 'hello world'
573
+ ]
574
+ }
575
+ };
576
+ const result = await resolver.resolve(value, context);
577
+ expect(result.startsWith('0x')).toBe(true);
578
+ expect(result.length % 2).toBe(0);
579
+ expect(result.length).toBeGreaterThan(10);
580
+ });
581
+ it('should handle string parameters correctly', async () => {
582
+ const value = {
583
+ type: 'abi-encode',
584
+ arguments: {
585
+ signature: 'setName(string)',
586
+ values: ['Alice']
587
+ }
588
+ };
589
+ const result = await resolver.resolve(value, context);
590
+ expect(result.startsWith('0x')).toBe(true);
591
+ const iface = new ethers_1.ethers.Interface(['function setName(string)']);
592
+ const decoded = iface.decodeFunctionData('setName', result);
593
+ expect(decoded[0]).toBe('Alice');
594
+ });
595
+ it('should handle array parameters', async () => {
596
+ const value = {
597
+ type: 'abi-encode',
598
+ arguments: {
599
+ signature: 'batchTransfer(address[])',
600
+ values: [['0x1234567890123456789012345678901234567890', '0x0987654321098765432109876543210987654321']]
601
+ }
602
+ };
603
+ const result = await resolver.resolve(value, context);
604
+ expect(result.startsWith('0x')).toBe(true);
605
+ const iface = new ethers_1.ethers.Interface(['function batchTransfer(address[])']);
606
+ const decoded = iface.decodeFunctionData('batchTransfer', result);
607
+ expect(decoded[0]).toEqual(['0x1234567890123456789012345678901234567890', '0x0987654321098765432109876543210987654321']);
608
+ });
609
+ it('should validate that signature is provided', async () => {
610
+ const value = {
611
+ type: 'abi-encode',
612
+ arguments: {
613
+ signature: null,
614
+ values: []
615
+ }
616
+ };
617
+ await expect(resolver.resolve(value, context)).rejects.toThrow('abi-encode: signature is required');
618
+ });
619
+ it('should validate that values array is provided', async () => {
620
+ const value = {
621
+ type: 'abi-encode',
622
+ arguments: {
623
+ signature: 'transfer(address)',
624
+ values: null
625
+ }
626
+ };
627
+ await expect(resolver.resolve(value, context)).rejects.toThrow('abi-encode: values array is required');
628
+ });
629
+ it('should handle invalid function signatures gracefully', async () => {
630
+ const originalConsoleLog = console.log;
631
+ console.log = jest.fn();
632
+ const value = {
633
+ type: 'abi-encode',
634
+ arguments: {
635
+ signature: 'invalid signature format',
636
+ values: []
637
+ }
638
+ };
639
+ await expect(resolver.resolve(value, context)).rejects.toThrow(/abi-encode: Failed to encode function data:/);
640
+ console.log = originalConsoleLog;
641
+ });
642
+ it('should handle mismatched parameter count', async () => {
643
+ const value = {
644
+ type: 'abi-encode',
645
+ arguments: {
646
+ signature: 'transfer(address,uint256)',
647
+ values: ['0x1234567890123456789012345678901234567890']
648
+ }
649
+ };
650
+ await expect(resolver.resolve(value, context)).rejects.toThrow(/abi-encode: Failed to encode function data:/);
651
+ });
652
+ it('should handle type mismatches gracefully', async () => {
653
+ const value = {
654
+ type: 'abi-encode',
655
+ arguments: {
656
+ signature: 'transfer(address,uint256)',
657
+ values: ['not-an-address', 'not-a-number']
658
+ }
659
+ };
660
+ await expect(resolver.resolve(value, context)).rejects.toThrow(/abi-encode: Failed to encode function data:/);
661
+ });
662
+ });
663
+ describe('abi-pack', () => {
664
+ it('should pack a single uint256 value', async () => {
665
+ const value = {
666
+ type: 'abi-pack',
667
+ arguments: {
668
+ types: ['uint256'],
669
+ values: ['42']
670
+ }
671
+ };
672
+ const result = await resolver.resolve(value, context);
673
+ expect(result).toBe('0x000000000000000000000000000000000000000000000000000000000000002a');
674
+ });
675
+ it('should pack multiple values with different types', async () => {
676
+ const value = {
677
+ type: 'abi-pack',
678
+ arguments: {
679
+ types: ['uint256', 'uint8', 'address'],
680
+ values: ['42', '255', '0x1234567890123456789012345678901234567890']
681
+ }
682
+ };
683
+ const result = await resolver.resolve(value, context);
684
+ expect(result.startsWith('0x')).toBe(true);
685
+ expect(result.length).toBeGreaterThan(2);
686
+ });
687
+ it('should pack string values correctly', async () => {
688
+ const value = {
689
+ type: 'abi-pack',
690
+ arguments: {
691
+ types: ['string'],
692
+ values: ['hello']
693
+ }
694
+ };
695
+ const result = await resolver.resolve(value, context);
696
+ expect(result.startsWith('0x')).toBe(true);
697
+ expect(result).toBe('0x68656c6c6f');
698
+ });
699
+ it('should pack bytes values correctly', async () => {
700
+ const value = {
701
+ type: 'abi-pack',
702
+ arguments: {
703
+ types: ['bytes'],
704
+ values: ['0xdeadbeef']
705
+ }
706
+ };
707
+ const result = await resolver.resolve(value, context);
708
+ expect(result).toBe('0xdeadbeef');
709
+ });
710
+ it('should pack uint8 values without padding', async () => {
711
+ const value = {
712
+ type: 'abi-pack',
713
+ arguments: {
714
+ types: ['uint8', 'uint8'],
715
+ values: ['255', '128']
716
+ }
717
+ };
718
+ const result = await resolver.resolve(value, context);
719
+ expect(result).toBe('0xff80');
720
+ });
721
+ it('should pack address values correctly', async () => {
722
+ const value = {
723
+ type: 'abi-pack',
724
+ arguments: {
725
+ types: ['address'],
726
+ values: ['0x1234567890123456789012345678901234567890']
727
+ }
728
+ };
729
+ const result = await resolver.resolve(value, context);
730
+ expect(result).toBe('0x1234567890123456789012345678901234567890');
731
+ });
732
+ it('should pack boolean values correctly', async () => {
733
+ const value = {
734
+ type: 'abi-pack',
735
+ arguments: {
736
+ types: ['bool', 'bool'],
737
+ values: [true, false]
738
+ }
739
+ };
740
+ const result = await resolver.resolve(value, context);
741
+ expect(result).toBe('0x0100');
742
+ });
743
+ it('should pack mixed types in correct order', async () => {
744
+ const value = {
745
+ type: 'abi-pack',
746
+ arguments: {
747
+ types: ['uint8', 'address', 'uint8'],
748
+ values: ['42', '0x1234567890123456789012345678901234567890', '255']
749
+ }
750
+ };
751
+ const result = await resolver.resolve(value, context);
752
+ expect(result.length).toBe(46);
753
+ expect(result.startsWith('0x2a')).toBe(true);
754
+ expect(result.endsWith('ff')).toBe(true);
755
+ });
756
+ it('should resolve values from context before packing', async () => {
757
+ context.setOutput('myValue', '100');
758
+ context.setOutput('myAddress', '0x1234567890123456789012345678901234567890');
759
+ const value = {
760
+ type: 'abi-pack',
761
+ arguments: {
762
+ types: ['uint256', 'address'],
763
+ values: ['{{myValue}}', '{{myAddress}}']
764
+ }
765
+ };
766
+ const result = await resolver.resolve(value, context);
767
+ expect(result.startsWith('0x')).toBe(true);
768
+ expect(result.length).toBeGreaterThan(2);
769
+ });
770
+ it('should validate that types array is provided', async () => {
771
+ const value = {
772
+ type: 'abi-pack',
773
+ arguments: {
774
+ types: null,
775
+ values: ['42']
776
+ }
777
+ };
778
+ await expect(resolver.resolve(value, context)).rejects.toThrow('abi-pack: types array is required');
779
+ });
780
+ it('should validate that values array is provided', async () => {
781
+ const value = {
782
+ type: 'abi-pack',
783
+ arguments: {
784
+ types: ['uint256'],
785
+ values: null
786
+ }
787
+ };
788
+ await expect(resolver.resolve(value, context)).rejects.toThrow('abi-pack: values array is required');
789
+ });
790
+ it('should validate that types and values arrays have same length', async () => {
791
+ const value = {
792
+ type: 'abi-pack',
793
+ arguments: {
794
+ types: ['uint256', 'uint8'],
795
+ values: ['42']
796
+ }
797
+ };
798
+ await expect(resolver.resolve(value, context)).rejects.toThrow('abi-pack: types array length (2) must match values array length (1)');
799
+ });
800
+ it('should validate that all types are strings', async () => {
801
+ const value = {
802
+ type: 'abi-pack',
803
+ arguments: {
804
+ types: ['uint256', 123],
805
+ values: ['42', '255']
806
+ }
807
+ };
808
+ await expect(resolver.resolve(value, context)).rejects.toThrow('abi-pack: all types must be strings');
809
+ });
810
+ it('should handle invalid type gracefully', async () => {
811
+ const value = {
812
+ type: 'abi-pack',
813
+ arguments: {
814
+ types: ['invalidType'],
815
+ values: ['42']
816
+ }
817
+ };
818
+ await expect(resolver.resolve(value, context)).rejects.toThrow(/abi-pack: Failed to pack values:/);
819
+ });
820
+ it('should handle type mismatches gracefully', async () => {
821
+ const value = {
822
+ type: 'abi-pack',
823
+ arguments: {
824
+ types: ['uint256'],
825
+ values: ['not-a-number']
826
+ }
827
+ };
828
+ await expect(resolver.resolve(value, context)).rejects.toThrow(/abi-pack: Failed to pack values:/);
829
+ });
830
+ it('should handle empty arrays', async () => {
831
+ const value = {
832
+ type: 'abi-pack',
833
+ arguments: {
834
+ types: [],
835
+ values: []
836
+ }
837
+ };
838
+ const result = await resolver.resolve(value, context);
839
+ expect(result).toBe('0x');
840
+ });
841
+ it('should pack large numbers correctly', async () => {
842
+ const value = {
843
+ type: 'abi-pack',
844
+ arguments: {
845
+ types: ['uint256'],
846
+ values: ['115792089237316195423570985008687907853269984665640564039457584007913129639935']
847
+ }
848
+ };
849
+ const result = await resolver.resolve(value, context);
850
+ expect(result).toBe('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
851
+ });
852
+ it('should demonstrate difference from abi-encode', async () => {
853
+ const packValue = {
854
+ type: 'abi-pack',
855
+ arguments: {
856
+ types: ['uint8', 'uint8'],
857
+ values: ['42', '255']
858
+ }
859
+ };
860
+ const encodeValue = {
861
+ type: 'abi-encode',
862
+ arguments: {
863
+ signature: 'test(uint8,uint8)',
864
+ values: ['42', '255']
865
+ }
866
+ };
867
+ const packResult = await resolver.resolve(packValue, context);
868
+ const encodeResult = await resolver.resolve(encodeValue, context);
869
+ expect(packResult).toBe('0x2aff');
870
+ expect(encodeResult.length).toBeGreaterThan(packResult.length);
871
+ });
872
+ });
873
+ describe('artifact function expressions', () => {
874
+ beforeEach(() => {
875
+ const testArtifact1 = {
876
+ contractName: 'TestContract',
877
+ abi: [{ "type": "function", "name": "test", "inputs": [], "outputs": [{ "type": "uint256" }] }],
878
+ bytecode: '0x608060405234801561000f575f5ffd5b50602a5f526020601ff3',
879
+ _path: '/test/TestContract.json',
880
+ _hash: 'abc123'
881
+ };
882
+ const testArtifact2 = {
883
+ contractName: 'ContractWithoutBytecode',
884
+ abi: [{ "type": "function", "name": "example", "inputs": [], "outputs": [] }],
885
+ bytecode: '',
886
+ _path: '/test/ContractWithoutBytecode.json',
887
+ _hash: 'def456'
888
+ };
889
+ const testArtifact3 = {
890
+ contractName: 'ContractWithoutABI',
891
+ abi: [],
892
+ bytecode: '0x608060405234801561000f575f5ffd5b50602a5f526020601ff4',
893
+ _path: '/test/ContractWithoutABI.json',
894
+ _hash: 'ghi789'
895
+ };
896
+ mockRegistry.addForTesting(testArtifact1);
897
+ mockRegistry.addForTesting(testArtifact2);
898
+ mockRegistry.addForTesting(testArtifact3);
899
+ });
900
+ describe('Contract(...).creationCode', () => {
901
+ it('should return bytecode for valid artifact', async () => {
902
+ const result = await resolver.resolve('{{Contract(TestContract).creationCode}}', context);
903
+ expect(result).toBe('0x608060405234801561000f575f5ffd5b50602a5f526020601ff3');
904
+ });
905
+ it('should return bytecode for valid artifact using initCode alias', async () => {
906
+ const result = await resolver.resolve('{{Contract(TestContract).creationCode}}', context);
907
+ expect(result).toBe('0x608060405234801561000f575f5ffd5b50602a5f526020601ff3');
908
+ });
909
+ it('should resolve nested in value resolver objects', async () => {
910
+ const value = {
911
+ type: 'constructor-encode',
912
+ arguments: {
913
+ creationCode: '{{Contract(TestContract).creationCode}}',
914
+ types: [],
915
+ values: []
916
+ }
917
+ };
918
+ const result = await resolver.resolve(value, context);
919
+ expect(result).toBe('0x608060405234801561000f575f5ffd5b50602a5f526020601ff3');
920
+ });
921
+ it('should throw error for non-existent artifact', async () => {
922
+ await expect(resolver.resolve('{{Contract(NonExistent).creationCode}}', context))
923
+ .rejects.toThrow('Artifact not found for reference: "NonExistent"');
924
+ });
925
+ it('should throw error for artifact missing bytecode', async () => {
926
+ const artifactWithoutBytecode = {
927
+ contractName: 'ContractWithoutBytecode',
928
+ abi: [],
929
+ bytecode: '',
930
+ _path: '/test/ContractWithoutBytecode.json',
931
+ _hash: 'empty123'
932
+ };
933
+ mockRegistry.addForTesting(artifactWithoutBytecode);
934
+ const contract = mockRegistry.lookup('ContractWithoutBytecode');
935
+ expect(contract?.creationCode).toBe('');
936
+ const result = await resolver.resolve('{{Contract(ContractWithoutBytecode).creationCode}}', context);
937
+ expect(result).toBe('');
938
+ });
939
+ it('should handle artifacts with null bytecode', async () => {
940
+ const artifactWithNullBytecode = {
941
+ contractName: 'NullBytecodeContract',
942
+ abi: [],
943
+ bytecode: null,
944
+ _path: '/test/NullBytecodeContract.json',
945
+ _hash: 'null123'
946
+ };
947
+ expect(() => mockRegistry.addForTesting(artifactWithNullBytecode))
948
+ .toThrow('Cannot hydrate contract from /test/NullBytecodeContract.json: missing creation code');
949
+ });
950
+ it('should handle artifacts with undefined bytecode', async () => {
951
+ const artifactWithUndefinedBytecode = {
952
+ contractName: 'UndefinedBytecodeContract',
953
+ abi: [],
954
+ bytecode: undefined,
955
+ _path: '/test/UndefinedBytecodeContract.json',
956
+ _hash: 'undef123'
957
+ };
958
+ expect(() => mockRegistry.addForTesting(artifactWithUndefinedBytecode))
959
+ .toThrow('Cannot hydrate contract from /test/UndefinedBytecodeContract.json: missing creation code');
960
+ });
961
+ });
962
+ describe('Contract(...).abi', () => {
963
+ it('should return abi for valid artifact', async () => {
964
+ const result = await resolver.resolve('{{Contract(TestContract).abi}}', context);
965
+ expect(result).toEqual([{ "type": "function", "name": "test", "inputs": [], "outputs": [{ "type": "uint256" }] }]);
966
+ });
967
+ it('should resolve nested in value resolver objects', async () => {
968
+ const abiValue = await resolver.resolve('{{Contract(TestContract).abi}}', context);
969
+ context.setOutput('contractAbi', abiValue);
970
+ const resolvedAbi = await resolver.resolve('{{contractAbi}}', context);
971
+ expect(resolvedAbi).toEqual([{ "type": "function", "name": "test", "inputs": [], "outputs": [{ "type": "uint256" }] }]);
972
+ });
973
+ it('should throw error for non-existent artifact', async () => {
974
+ await expect(resolver.resolve('{{Contract(NonExistent).abi}}', context))
975
+ .rejects.toThrow('Artifact not found for reference: "NonExistent"');
976
+ });
977
+ it('should return empty abi for artifact with empty abi array', async () => {
978
+ const result = await resolver.resolve('{{Contract(ContractWithoutABI).abi}}', context);
979
+ expect(result).toEqual([]);
980
+ });
981
+ it('should handle artifacts with null abi', async () => {
982
+ const artifactWithNullAbi = {
983
+ contractName: 'NullAbiContract',
984
+ abi: null,
985
+ bytecode: '0x123',
986
+ _path: '/test/NullAbiContract.json',
987
+ _hash: 'nullabi123'
988
+ };
989
+ mockRegistry.addForTesting(artifactWithNullAbi);
990
+ await expect(resolver.resolve('{{Contract(NullAbiContract).abi}}', context))
991
+ .rejects.toThrow('Property "abi" does not exist on contract found for reference "NullAbiContract"');
992
+ });
993
+ it('should handle artifacts with undefined abi', async () => {
994
+ const artifactWithUndefinedAbi = {
995
+ contractName: 'UndefinedAbiContract',
996
+ abi: undefined,
997
+ bytecode: '0x123',
998
+ _path: '/test/UndefinedAbiContract.json',
999
+ _hash: 'undefabi123'
1000
+ };
1001
+ mockRegistry.addForTesting(artifactWithUndefinedAbi);
1002
+ await expect(resolver.resolve('{{Contract(UndefinedAbiContract).abi}}', context))
1003
+ .rejects.toThrow('Property "abi" does not exist on contract found for reference "UndefinedAbiContract"');
1004
+ });
1005
+ });
1006
+ describe('Contract(...).buildInfoId', () => {
1007
+ it('should return buildInfoId for contract hydrated from build-info file', async () => {
1008
+ const buildInfoArtifact = {
1009
+ contractName: 'TestBuildInfoContract',
1010
+ abi: [{ "type": "function", "name": "test", "inputs": [], "outputs": [{ "type": "uint256" }] }],
1011
+ bytecode: '0x608060405234801561000f575f5ffd5b50602a5f526020601ff3',
1012
+ sourceName: 'src/TestContract.sol',
1013
+ compiler: { name: 'solc', version: '0.8.19' },
1014
+ buildInfoId: 'src/TestContract.sol:TestContract',
1015
+ _path: '/test/build-info/test.json',
1016
+ _hash: 'buildinfo123'
1017
+ };
1018
+ mockRegistry.addForTesting(buildInfoArtifact);
1019
+ const result = await resolver.resolve('{{Contract(TestBuildInfoContract).buildInfoId}}', context);
1020
+ expect(result).toBe('src/TestContract.sol:TestContract');
1021
+ });
1022
+ it('should throw error for non-existent artifact', async () => {
1023
+ await expect(resolver.resolve('{{Contract(NonExistent).buildInfoId}}', context))
1024
+ .rejects.toThrow('Artifact not found for reference: "NonExistent"');
1025
+ });
1026
+ it('should throw error for contract that was not hydrated from build-info file', async () => {
1027
+ await expect(resolver.resolve('{{Contract(TestContract).buildInfoId}}', context))
1028
+ .rejects.toThrow('Property "buildInfoId" does not exist on contract found for reference "TestContract"');
1029
+ });
1030
+ });
1031
+ describe('invalid Contract expressions', () => {
1032
+ it('should throw error for unknown function names', async () => {
1033
+ await expect(resolver.resolve('{{unknownFunction(TestContract)}}', context))
1034
+ .rejects.toThrow('Failed to resolve expression "{{unknownFunction(TestContract)}}"');
1035
+ });
1036
+ it('should throw error for malformed expressions', async () => {
1037
+ await expect(resolver.resolve('{{creationCode}}', context))
1038
+ .rejects.toThrow('Failed to resolve expression "{{creationCode}}"');
1039
+ });
1040
+ it('should throw error for invalid syntax', async () => {
1041
+ await expect(resolver.resolve('{{creationCode TestContract}}', context))
1042
+ .rejects.toThrow('Failed to resolve expression "{{creationCode TestContract}}"');
1043
+ });
1044
+ it('should throw error for empty function calls', async () => {
1045
+ await expect(resolver.resolve('{{Contract().creationCode}}', context)).rejects.toThrow('Artifact not found for reference: ""');
1046
+ });
1047
+ it('should throw error for function calls with whitespace only', async () => {
1048
+ await expect(resolver.resolve('{{Contract( ).creationCode}}', context)).rejects.toThrow('Artifact not found for reference: ""');
1049
+ });
1050
+ it('should handle function calls with extra whitespace in argument', async () => {
1051
+ const result = await resolver.resolve('{{Contract( TestContract ).creationCode}}', context);
1052
+ expect(result).toBe('0x608060405234801561000f575f5ffd5b50602a5f526020601ff3');
1053
+ });
1054
+ it('should handle mixed case function names correctly', async () => {
1055
+ await expect(resolver.resolve('{{CreationCode(TestContract)}}', context))
1056
+ .rejects.toThrow('Failed to resolve expression "{{CreationCode(TestContract)}}"');
1057
+ });
1058
+ it('should handle function calls with multiple arguments (should fail)', async () => {
1059
+ await expect(resolver.resolve('{{Contract(TestContract, ExtraArg).creationCode}}', context))
1060
+ .rejects.toThrow('Artifact not found for reference: "TestContract, ExtraArg"');
1061
+ });
1062
+ });
1063
+ describe('edge cases', () => {
1064
+ it('should handle artifacts identified by contract name', async () => {
1065
+ const pathArtifact = {
1066
+ contractName: 'PathContract',
1067
+ abi: [],
1068
+ bytecode: '0xabcdef',
1069
+ _path: '/very/long/path/to/contracts/PathContract.json',
1070
+ _hash: 'path123'
1071
+ };
1072
+ mockRegistry.addForTesting(pathArtifact);
1073
+ const result = await resolver.resolve('{{Contract(PathContract).creationCode}}', context);
1074
+ expect(result).toBe('0xabcdef');
1075
+ });
1076
+ it('should handle artifacts with special characters in names', async () => {
1077
+ const specialArtifact = {
1078
+ contractName: 'Special-Contract_v2',
1079
+ abi: [],
1080
+ bytecode: '0xspecial',
1081
+ _path: '/test/Special-Contract_v2.json',
1082
+ _hash: 'special123'
1083
+ };
1084
+ mockRegistry.addForTesting(specialArtifact);
1085
+ const result = await resolver.resolve('{{Contract(Special-Contract_v2).creationCode}}', context);
1086
+ expect(result).toBe('0xspecial');
1087
+ });
1088
+ it('should be case sensitive for artifact names', async () => {
1089
+ await expect(resolver.resolve('{{Contract(testcontract).creationCode}}', context))
1090
+ .rejects.toThrow('Artifact not found for reference: "testcontract"');
1091
+ });
1092
+ it('should handle resolution with context variables for artifact names', async () => {
1093
+ context.setOutput('contractName', 'TestContract');
1094
+ const contractName = await resolver.resolve('{{contractName}}', context);
1095
+ const result = await resolver.resolve(`{{Contract(${contractName}).creationCode}}`, context);
1096
+ expect(result).toBe('0x608060405234801561000f575f5ffd5b50602a5f526020601ff3');
1097
+ });
1098
+ });
1099
+ });
1100
+ describe('call', () => {
1101
+ let testContractAddress;
1102
+ let anvilProvider;
1103
+ beforeEach(async () => {
1104
+ anvilProvider = context.provider;
1105
+ testContractAddress = '0x5FbDB2315678afecb367f032d93F642f64180aa3';
1106
+ const miniContractBytecode = '0x608060405234801561000f575f5ffd5b5060043610610034575f3560e01c80636df5b97a14610038578063f8a8fd6d14610068575b5f5ffd5b610052600480360381019061004d91906100da565b610086565b60405161005f9190610127565b60405180910390f35b61007061009b565b60405161007d9190610127565b60405180910390f35b5f8183610093919061016d565b905092915050565b5f602a905090565b5f5ffd5b5f819050919050565b6100b9816100a7565b81146100c3575f5ffd5b50565b5f813590506100d4816100b0565b92915050565b5f5f604083850312156100f0576100ef6100a3565b5b5f6100fd858286016100c6565b925050602061010e858286016100c6565b9150509250929050565b610121816100a7565b82525050565b5f60208201905061013a5f830184610118565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610177826100a7565b9150610182836100a7565b9250828202610190816100a7565b915082820484148315176101a7576101a6610140565b5b509291505056fea264697066735822122071d40daa3d2beacd91f29d29ccf1c0b6f312e805f50b37166267c0a2a55e6e6164736f6c634300081c0033';
1107
+ await anvilProvider.send('anvil_setCode', [testContractAddress, miniContractBytecode]);
1108
+ });
1109
+ it('should call test() function and return 42', async () => {
1110
+ const value = {
1111
+ type: 'call',
1112
+ arguments: {
1113
+ to: testContractAddress,
1114
+ signature: 'test() returns (uint256)',
1115
+ values: []
1116
+ }
1117
+ };
1118
+ const result = await resolver.resolve(value, context);
1119
+ expect(result).toBe(42n);
1120
+ });
1121
+ it('should call multiply2numbers with parameters', async () => {
1122
+ const value = {
1123
+ type: 'call',
1124
+ arguments: {
1125
+ to: testContractAddress,
1126
+ signature: 'multiply2numbers(uint256,uint256) returns (uint256)',
1127
+ values: ['7', '6']
1128
+ }
1129
+ };
1130
+ const result = await resolver.resolve(value, context);
1131
+ expect(result).toBe(42n);
1132
+ });
1133
+ it('should resolve address from context variable', async () => {
1134
+ context.setOutput('contractAddr', testContractAddress);
1135
+ const value = {
1136
+ type: 'call',
1137
+ arguments: {
1138
+ to: '{{contractAddr}}',
1139
+ signature: 'test() returns (uint256)',
1140
+ values: []
1141
+ }
1142
+ };
1143
+ const result = await resolver.resolve(value, context);
1144
+ expect(result).toBe(42n);
1145
+ });
1146
+ it('should resolve parameters from context variables', async () => {
1147
+ context.setOutput('firstNumber', '15');
1148
+ context.setOutput('secondNumber', '25');
1149
+ const value = {
1150
+ type: 'call',
1151
+ arguments: {
1152
+ to: testContractAddress,
1153
+ signature: 'multiply2numbers(uint256,uint256) returns (uint256)',
1154
+ values: ['{{firstNumber}}', '{{secondNumber}}']
1155
+ }
1156
+ };
1157
+ const result = await resolver.resolve(value, context);
1158
+ expect(result).toBe(375n);
1159
+ });
1160
+ it('should handle large number multiplication', async () => {
1161
+ const value = {
1162
+ type: 'call',
1163
+ arguments: {
1164
+ to: testContractAddress,
1165
+ signature: 'multiply2numbers(uint256,uint256) returns (uint256)',
1166
+ values: ['1000000000000000000', '2000000000000000000']
1167
+ }
1168
+ };
1169
+ const result = await resolver.resolve(value, context);
1170
+ expect(result).toBe(2000000000000000000000000000000000000n);
1171
+ });
1172
+ it('should throw error when calling non-existent function on deployed contract', async () => {
1173
+ const value = {
1174
+ type: 'call',
1175
+ arguments: {
1176
+ to: testContractAddress,
1177
+ signature: 'nonExistentFunction() view returns (uint256)',
1178
+ values: []
1179
+ }
1180
+ };
1181
+ await expect(resolver.resolve(value, context)).rejects.toThrow(/call: Failed to execute contract call:/);
1182
+ });
1183
+ it('should throw error for mismatched parameter count', async () => {
1184
+ const value = {
1185
+ type: 'call',
1186
+ arguments: {
1187
+ to: testContractAddress,
1188
+ signature: 'multiply2numbers(uint256,uint256) returns (uint256)',
1189
+ values: ['10']
1190
+ }
1191
+ };
1192
+ await expect(resolver.resolve(value, context)).rejects.toThrow(/call: Failed to execute contract call:/);
1193
+ });
1194
+ it('should handle type mismatches gracefully', async () => {
1195
+ const value = {
1196
+ type: 'call',
1197
+ arguments: {
1198
+ to: testContractAddress,
1199
+ signature: 'multiply2numbers(uint256,uint256) returns (uint256)',
1200
+ values: ['not-a-number', 'also-not-a-number']
1201
+ }
1202
+ };
1203
+ await expect(resolver.resolve(value, context)).rejects.toThrow(/call: Failed to execute contract call:/);
1204
+ });
1205
+ it('should throw error when no target address provided', async () => {
1206
+ const value = {
1207
+ type: 'call',
1208
+ arguments: {
1209
+ signature: 'test() returns (uint256)',
1210
+ values: []
1211
+ }
1212
+ };
1213
+ await expect(resolver.resolve(value, context)).rejects.toThrow('call: target address (to) is required');
1214
+ });
1215
+ it('should throw error for invalid target address', async () => {
1216
+ const value = {
1217
+ type: 'call',
1218
+ arguments: {
1219
+ to: 'invalid-address',
1220
+ signature: 'test() returns (uint256)',
1221
+ values: []
1222
+ }
1223
+ };
1224
+ await expect(resolver.resolve(value, context)).rejects.toThrow('call: invalid target address: invalid-address');
1225
+ });
1226
+ it('should throw error when no signature provided', async () => {
1227
+ const value = {
1228
+ type: 'call',
1229
+ arguments: {
1230
+ to: testContractAddress,
1231
+ signature: null,
1232
+ values: []
1233
+ }
1234
+ };
1235
+ await expect(resolver.resolve(value, context)).rejects.toThrow('call: function signature is required');
1236
+ });
1237
+ it('should throw error when no values array provided', async () => {
1238
+ const value = {
1239
+ type: 'call',
1240
+ arguments: {
1241
+ to: testContractAddress,
1242
+ signature: 'test() returns (uint256)',
1243
+ values: null
1244
+ }
1245
+ };
1246
+ await expect(resolver.resolve(value, context)).rejects.toThrow('call: values array is required');
1247
+ });
1248
+ it('should throw error for invalid function signature', async () => {
1249
+ const originalConsoleLog = console.log;
1250
+ console.log = jest.fn();
1251
+ const value = {
1252
+ type: 'call',
1253
+ arguments: {
1254
+ to: testContractAddress,
1255
+ signature: 'invalid signature format',
1256
+ values: []
1257
+ }
1258
+ };
1259
+ await expect(resolver.resolve(value, context)).rejects.toThrow(/call: Failed to execute contract call:/);
1260
+ console.log = originalConsoleLog;
1261
+ });
1262
+ it('should handle null address gracefully', async () => {
1263
+ const value = {
1264
+ type: 'call',
1265
+ arguments: {
1266
+ to: null,
1267
+ signature: 'test() returns (uint256)',
1268
+ values: []
1269
+ }
1270
+ };
1271
+ await expect(resolver.resolve(value, context)).rejects.toThrow('call: target address (to) is required');
1272
+ });
1273
+ it('should handle undefined address gracefully', async () => {
1274
+ const value = {
1275
+ type: 'call',
1276
+ arguments: {
1277
+ to: undefined,
1278
+ signature: 'test() returns (uint256)',
1279
+ values: []
1280
+ }
1281
+ };
1282
+ await expect(resolver.resolve(value, context)).rejects.toThrow('call: target address (to) is required');
1283
+ });
1284
+ it('should work with zero parameters', async () => {
1285
+ const value = {
1286
+ type: 'call',
1287
+ arguments: {
1288
+ to: testContractAddress,
1289
+ signature: 'test() returns (uint256)',
1290
+ values: []
1291
+ }
1292
+ };
1293
+ const result = await resolver.resolve(value, context);
1294
+ expect(result).toBe(42n);
1295
+ });
1296
+ it('should work with string parameters converted to numbers', async () => {
1297
+ const value = {
1298
+ type: 'call',
1299
+ arguments: {
1300
+ to: testContractAddress,
1301
+ signature: 'multiply2numbers(uint256,uint256) returns (uint256)',
1302
+ values: ['100', '200']
1303
+ }
1304
+ };
1305
+ const result = await resolver.resolve(value, context);
1306
+ expect(result).toBe(20000n);
1307
+ });
1308
+ });
1309
+ describe('contract-exists', () => {
1310
+ let testContractAddress;
1311
+ let anvilProvider;
1312
+ beforeEach(async () => {
1313
+ anvilProvider = context.provider;
1314
+ testContractAddress = '0x5FbDB2315678afecb367f032d93F642f64180aa3';
1315
+ const miniContractBytecode = '0x608060405234801561000f575f5ffd5b5060043610610034575f3560e01c80636df5b97a14610038578063f8a8fd6d14610068575b5f5ffd5b610052600480360381019061004d91906100da565b610086565b60405161005f9190610127565b60405180910390f35b61007061009b565b60405161007d9190610127565b60405180910390f35b5f8183610093919061016d565b905092915050565b5f602a905090565b5f5ffd5b5f819050919050565b6100b9816100a7565b81146100c3575f5ffd5b50565b5f813590506100d4816100b0565b92915050565b5f5f604083850312156100f0576100ef6100a3565b5b5f6100fd858286016100c6565b925050602061010e858286016100c6565b9150509250929050565b610121816100a7565b82525050565b5f60208201905061013a5f830184610118565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610177826100a7565b9150610182836100a7565b9250828202610190816100a7565b915082820484148315176101a7576101a6610140565b5b509291505056fea264697066735822122071d40daa3d2beacd91f29d29ccf1c0b6f312e805f50b37166267c0a2a55e6e6164736f6c634300081c0033';
1316
+ await anvilProvider.send('anvil_setCode', [testContractAddress, miniContractBytecode]);
1317
+ });
1318
+ it('should return true if contract exists', async () => {
1319
+ const value = {
1320
+ type: 'contract-exists',
1321
+ arguments: {
1322
+ address: testContractAddress,
1323
+ },
1324
+ };
1325
+ const result = await resolver.resolve(value, context);
1326
+ expect(result).toBe(true);
1327
+ });
1328
+ it('should return false if contract does not exist', async () => {
1329
+ const value = {
1330
+ type: 'contract-exists',
1331
+ arguments: {
1332
+ address: '0x0000000000000000000000000000000000000001',
1333
+ },
1334
+ };
1335
+ const result = await resolver.resolve(value, context);
1336
+ expect(result).toBe(false);
1337
+ });
1338
+ it('should throw error for null address', async () => {
1339
+ const value = {
1340
+ type: 'contract-exists',
1341
+ arguments: {
1342
+ address: null,
1343
+ },
1344
+ };
1345
+ await expect(resolver.resolve(value, context)).rejects.toThrow('contract-exists: invalid address: null');
1346
+ });
1347
+ it('should throw error for undefined address', async () => {
1348
+ const value = {
1349
+ type: 'contract-exists',
1350
+ arguments: {
1351
+ address: undefined,
1352
+ },
1353
+ };
1354
+ await expect(resolver.resolve(value, context)).rejects.toThrow('contract-exists: invalid address: undefined');
1355
+ });
1356
+ it('should throw error for invalid address', async () => {
1357
+ const value = {
1358
+ type: 'contract-exists',
1359
+ arguments: {
1360
+ address: 'invalid-address',
1361
+ },
1362
+ };
1363
+ await expect(resolver.resolve(value, context)).rejects.toThrow('contract-exists: invalid address: invalid-address');
1364
+ });
1365
+ });
1366
+ });
1367
+ //# sourceMappingURL=resolver.spec.js.map