@layerzerolabs/protocol-starknet-v2 0.0.34

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 (504) hide show
  1. package/.turbo/turbo-build.log +186 -0
  2. package/.turbo/turbo-lint.log +71 -0
  3. package/.turbo/turbo-test.log +937 -0
  4. package/README.md +41 -0
  5. package/Scarb.lock +211 -0
  6. package/Scarb.toml +2 -0
  7. package/dist/4XD3ZRZ4.cjs +301 -0
  8. package/dist/4XD3ZRZ4.cjs.map +1 -0
  9. package/dist/4Z5IPBC3.js +299 -0
  10. package/dist/4Z5IPBC3.js.map +1 -0
  11. package/dist/5NEZDLVQ.cjs +474 -0
  12. package/dist/5NEZDLVQ.cjs.map +1 -0
  13. package/dist/6JYCOKDE.js +472 -0
  14. package/dist/6JYCOKDE.js.map +1 -0
  15. package/dist/7C4PFMIZ.cjs +1288 -0
  16. package/dist/7C4PFMIZ.cjs.map +1 -0
  17. package/dist/7ZSGGZUE.js +1229 -0
  18. package/dist/7ZSGGZUE.js.map +1 -0
  19. package/dist/ARHOGUYH.cjs +2136 -0
  20. package/dist/ARHOGUYH.cjs.map +1 -0
  21. package/dist/CRCRIUFX.js +1264 -0
  22. package/dist/CRCRIUFX.js.map +1 -0
  23. package/dist/DB7CQSED.cjs +430 -0
  24. package/dist/DB7CQSED.cjs.map +1 -0
  25. package/dist/DFXLWHYP.cjs +1266 -0
  26. package/dist/DFXLWHYP.cjs.map +1 -0
  27. package/dist/EOLZCMCK.js +988 -0
  28. package/dist/EOLZCMCK.js.map +1 -0
  29. package/dist/FFDPTOWG.cjs +331 -0
  30. package/dist/FFDPTOWG.cjs.map +1 -0
  31. package/dist/FOJGEAIO.js +2134 -0
  32. package/dist/FOJGEAIO.js.map +1 -0
  33. package/dist/IWIUMVGB.js +629 -0
  34. package/dist/IWIUMVGB.js.map +1 -0
  35. package/dist/MUEN6AWV.cjs +697 -0
  36. package/dist/MUEN6AWV.cjs.map +1 -0
  37. package/dist/ORE6VBZ4.cjs +990 -0
  38. package/dist/ORE6VBZ4.cjs.map +1 -0
  39. package/dist/OUFKWPZ7.js +732 -0
  40. package/dist/OUFKWPZ7.js.map +1 -0
  41. package/dist/T2QTYQXJ.js +1229 -0
  42. package/dist/T2QTYQXJ.js.map +1 -0
  43. package/dist/UPJTM7BR.cjs +631 -0
  44. package/dist/UPJTM7BR.cjs.map +1 -0
  45. package/dist/VNVNX2P3.cjs +1231 -0
  46. package/dist/VNVNX2P3.cjs.map +1 -0
  47. package/dist/VUOMXK5T.js +6 -0
  48. package/dist/VUOMXK5T.js.map +1 -0
  49. package/dist/WISWRTDG.js +1286 -0
  50. package/dist/WISWRTDG.js.map +1 -0
  51. package/dist/WU5L7YIQ.cjs +1231 -0
  52. package/dist/WU5L7YIQ.cjs.map +1 -0
  53. package/dist/X3B5JDMZ.js +695 -0
  54. package/dist/X3B5JDMZ.js.map +1 -0
  55. package/dist/XYNBDBBV.cjs +297 -0
  56. package/dist/XYNBDBBV.cjs.map +1 -0
  57. package/dist/Y5JFPCYJ.cjs +734 -0
  58. package/dist/Y5JFPCYJ.cjs.map +1 -0
  59. package/dist/YEHL7IYO.js +295 -0
  60. package/dist/YEHL7IYO.js.map +1 -0
  61. package/dist/YJF4D23A.cjs +8 -0
  62. package/dist/YJF4D23A.cjs.map +1 -0
  63. package/dist/YTS44OEA.js +428 -0
  64. package/dist/YTS44OEA.js.map +1 -0
  65. package/dist/Z2NIUZMW.js +329 -0
  66. package/dist/Z2NIUZMW.js.map +1 -0
  67. package/dist/abis/blocked-message-lib.cjs +13 -0
  68. package/dist/abis/blocked-message-lib.cjs.map +1 -0
  69. package/dist/abis/blocked-message-lib.d.ts +338 -0
  70. package/dist/abis/blocked-message-lib.d.ts.map +1 -0
  71. package/dist/abis/blocked-message-lib.js +4 -0
  72. package/dist/abis/blocked-message-lib.js.map +1 -0
  73. package/dist/abis/dvn-fee-lib.cjs +13 -0
  74. package/dist/abis/dvn-fee-lib.cjs.map +1 -0
  75. package/dist/abis/dvn-fee-lib.d.ts +214 -0
  76. package/dist/abis/dvn-fee-lib.d.ts.map +1 -0
  77. package/dist/abis/dvn-fee-lib.js +4 -0
  78. package/dist/abis/dvn-fee-lib.js.map +1 -0
  79. package/dist/abis/dvn.cjs +13 -0
  80. package/dist/abis/dvn.cjs.map +1 -0
  81. package/dist/abis/dvn.d.ts +952 -0
  82. package/dist/abis/dvn.d.ts.map +1 -0
  83. package/dist/abis/dvn.js +4 -0
  84. package/dist/abis/dvn.js.map +1 -0
  85. package/dist/abis/endpoint-v2.cjs +13 -0
  86. package/dist/abis/endpoint-v2.cjs.map +1 -0
  87. package/dist/abis/endpoint-v2.d.ts +1580 -0
  88. package/dist/abis/endpoint-v2.d.ts.map +1 -0
  89. package/dist/abis/endpoint-v2.js +4 -0
  90. package/dist/abis/endpoint-v2.js.map +1 -0
  91. package/dist/abis/executor-fee-lib.cjs +13 -0
  92. package/dist/abis/executor-fee-lib.cjs.map +1 -0
  93. package/dist/abis/executor-fee-lib.d.ts +217 -0
  94. package/dist/abis/executor-fee-lib.d.ts.map +1 -0
  95. package/dist/abis/executor-fee-lib.js +4 -0
  96. package/dist/abis/executor-fee-lib.js.map +1 -0
  97. package/dist/abis/executor.cjs +13 -0
  98. package/dist/abis/executor.cjs.map +1 -0
  99. package/dist/abis/executor.d.ts +914 -0
  100. package/dist/abis/executor.d.ts.map +1 -0
  101. package/dist/abis/executor.js +4 -0
  102. package/dist/abis/executor.js.map +1 -0
  103. package/dist/abis/o-app.cjs +13 -0
  104. package/dist/abis/o-app.cjs.map +1 -0
  105. package/dist/abis/o-app.d.ts +311 -0
  106. package/dist/abis/o-app.d.ts.map +1 -0
  107. package/dist/abis/o-app.js +4 -0
  108. package/dist/abis/o-app.js.map +1 -0
  109. package/dist/abis/oft-adapter.cjs +13 -0
  110. package/dist/abis/oft-adapter.cjs.map +1 -0
  111. package/dist/abis/oft-adapter.d.ts +722 -0
  112. package/dist/abis/oft-adapter.d.ts.map +1 -0
  113. package/dist/abis/oft-adapter.js +4 -0
  114. package/dist/abis/oft-adapter.js.map +1 -0
  115. package/dist/abis/oft.cjs +13 -0
  116. package/dist/abis/oft.cjs.map +1 -0
  117. package/dist/abis/oft.d.ts +922 -0
  118. package/dist/abis/oft.d.ts.map +1 -0
  119. package/dist/abis/oft.js +4 -0
  120. package/dist/abis/oft.js.map +1 -0
  121. package/dist/abis/omni-counter.cjs +13 -0
  122. package/dist/abis/omni-counter.cjs.map +1 -0
  123. package/dist/abis/omni-counter.d.ts +459 -0
  124. package/dist/abis/omni-counter.d.ts.map +1 -0
  125. package/dist/abis/omni-counter.js +4 -0
  126. package/dist/abis/omni-counter.js.map +1 -0
  127. package/dist/abis/price-feed.cjs +13 -0
  128. package/dist/abis/price-feed.cjs.map +1 -0
  129. package/dist/abis/price-feed.d.ts +505 -0
  130. package/dist/abis/price-feed.d.ts.map +1 -0
  131. package/dist/abis/price-feed.js +4 -0
  132. package/dist/abis/price-feed.js.map +1 -0
  133. package/dist/abis/simple-message-lib.cjs +13 -0
  134. package/dist/abis/simple-message-lib.cjs.map +1 -0
  135. package/dist/abis/simple-message-lib.d.ts +535 -0
  136. package/dist/abis/simple-message-lib.d.ts.map +1 -0
  137. package/dist/abis/simple-message-lib.js +4 -0
  138. package/dist/abis/simple-message-lib.js.map +1 -0
  139. package/dist/abis/treasury.cjs +13 -0
  140. package/dist/abis/treasury.cjs.map +1 -0
  141. package/dist/abis/treasury.d.ts +240 -0
  142. package/dist/abis/treasury.d.ts.map +1 -0
  143. package/dist/abis/treasury.js +4 -0
  144. package/dist/abis/treasury.js.map +1 -0
  145. package/dist/abis/ultra-light-node.cjs +13 -0
  146. package/dist/abis/ultra-light-node.cjs.map +1 -0
  147. package/dist/abis/ultra-light-node.d.ts +900 -0
  148. package/dist/abis/ultra-light-node.d.ts.map +1 -0
  149. package/dist/abis/ultra-light-node.js +4 -0
  150. package/dist/abis/ultra-light-node.js.map +1 -0
  151. package/dist/index.cjs +78 -0
  152. package/dist/index.cjs.map +1 -0
  153. package/dist/index.d.ts +15 -0
  154. package/dist/index.d.ts.map +1 -0
  155. package/dist/index.js +17 -0
  156. package/dist/index.js.map +1 -0
  157. package/dist/scripts/build-abi.cjs +28 -0
  158. package/dist/scripts/build-abi.cjs.map +1 -0
  159. package/dist/scripts/build-abi.d.ts +2 -0
  160. package/dist/scripts/build-abi.d.ts.map +1 -0
  161. package/dist/scripts/build-abi.js +26 -0
  162. package/dist/scripts/build-abi.js.map +1 -0
  163. package/layerzero/README.md +244 -0
  164. package/layerzero/Scarb.lock +203 -0
  165. package/layerzero/Scarb.toml +30 -0
  166. package/layerzero/snfoundry.toml +11 -0
  167. package/layerzero/src/common/constants.cairo +26 -0
  168. package/layerzero/src/common/conversions.cairo +16 -0
  169. package/layerzero/src/common/guid.cairo +20 -0
  170. package/layerzero/src/common/packet_v1_codec.cairo +307 -0
  171. package/layerzero/src/common/structs/messaging.cairo +40 -0
  172. package/layerzero/src/common/structs/packet.cairo +31 -0
  173. package/layerzero/src/endpoint/constants.cairo +14 -0
  174. package/layerzero/src/endpoint/endpoint.cairo +688 -0
  175. package/layerzero/src/endpoint/errors.cairo +108 -0
  176. package/layerzero/src/endpoint/events.cairo +124 -0
  177. package/layerzero/src/endpoint/interfaces/endpoint.cairo +286 -0
  178. package/layerzero/src/endpoint/interfaces/layerzero_composer.cairo +62 -0
  179. package/layerzero/src/endpoint/interfaces/layerzero_receiver.cairo +63 -0
  180. package/layerzero/src/endpoint/message_lib_manager/errors.cairo +95 -0
  181. package/layerzero/src/endpoint/message_lib_manager/events.cairo +90 -0
  182. package/layerzero/src/endpoint/message_lib_manager/interface.cairo +449 -0
  183. package/layerzero/src/endpoint/message_lib_manager/message_lib_manager.cairo +720 -0
  184. package/layerzero/src/endpoint/message_lib_manager/structs.cairo +33 -0
  185. package/layerzero/src/endpoint/messaging_channel/errors.cairo +37 -0
  186. package/layerzero/src/endpoint/messaging_channel/events.cairo +58 -0
  187. package/layerzero/src/endpoint/messaging_channel/interface.cairo +171 -0
  188. package/layerzero/src/endpoint/messaging_channel/messaging_channel.cairo +453 -0
  189. package/layerzero/src/endpoint/messaging_composer/errors.cairo +46 -0
  190. package/layerzero/src/endpoint/messaging_composer/events.cairo +67 -0
  191. package/layerzero/src/endpoint/messaging_composer/interface.cairo +132 -0
  192. package/layerzero/src/endpoint/messaging_composer/messaging_composer.cairo +223 -0
  193. package/layerzero/src/lib.cairo +189 -0
  194. package/layerzero/src/message_lib/blocked_message_lib.cairo +114 -0
  195. package/layerzero/src/message_lib/interface.cairo +63 -0
  196. package/layerzero/src/message_lib/sml/errors.cairo +23 -0
  197. package/layerzero/src/message_lib/sml/events.cairo +32 -0
  198. package/layerzero/src/message_lib/sml/simple_message_lib.cairo +312 -0
  199. package/layerzero/src/message_lib/structs.cairo +22 -0
  200. package/layerzero/src/message_lib/uln/errors.cairo +128 -0
  201. package/layerzero/src/message_lib/uln/events.cairo +97 -0
  202. package/layerzero/src/message_lib/uln/interface.cairo +83 -0
  203. package/layerzero/src/message_lib/uln/options.cairo +64 -0
  204. package/layerzero/src/message_lib/uln/structs/executor_config.cairo +35 -0
  205. package/layerzero/src/message_lib/uln/structs/payment_info.cairo +7 -0
  206. package/layerzero/src/message_lib/uln/structs/uln_config.cairo +155 -0
  207. package/layerzero/src/message_lib/uln/structs/uln_config_storage_node.cairo +91 -0
  208. package/layerzero/src/message_lib/uln/structs/verification.cairo +7 -0
  209. package/layerzero/src/message_lib/uln/ultra_light_node.cairo +965 -0
  210. package/layerzero/src/oapps/common/oapp_options_type_3/errors.cairo +22 -0
  211. package/layerzero/src/oapps/common/oapp_options_type_3/events.cairo +6 -0
  212. package/layerzero/src/oapps/common/oapp_options_type_3/interface.cairo +34 -0
  213. package/layerzero/src/oapps/common/oapp_options_type_3/oapp_options_type_3.cairo +120 -0
  214. package/layerzero/src/oapps/common/oapp_options_type_3/structs.cairo +6 -0
  215. package/layerzero/src/oapps/counter/constants.cairo +3 -0
  216. package/layerzero/src/oapps/counter/counter.cairo +170 -0
  217. package/layerzero/src/oapps/counter/interface.cairo +27 -0
  218. package/layerzero/src/oapps/counter/structs.cairo +20 -0
  219. package/layerzero/src/oapps/message_inspector/interface.cairo +21 -0
  220. package/layerzero/src/oapps/oapp/errors.cairo +72 -0
  221. package/layerzero/src/oapps/oapp/events.cairo +9 -0
  222. package/layerzero/src/oapps/oapp/interface.cairo +67 -0
  223. package/layerzero/src/oapps/oapp/oapp.cairo +70 -0
  224. package/layerzero/src/oapps/oapp/oapp_core.cairo +448 -0
  225. package/layerzero/src/oapps/oft/errors.cairo +42 -0
  226. package/layerzero/src/oapps/oft/events.cairo +33 -0
  227. package/layerzero/src/oapps/oft/interface.cairo +87 -0
  228. package/layerzero/src/oapps/oft/oft.cairo +188 -0
  229. package/layerzero/src/oapps/oft/oft_adapter.cairo +175 -0
  230. package/layerzero/src/oapps/oft/oft_compose_msg_codec.cairo +128 -0
  231. package/layerzero/src/oapps/oft/oft_core.cairo +542 -0
  232. package/layerzero/src/oapps/oft/oft_msg_codec.cairo +131 -0
  233. package/layerzero/src/oapps/oft/structs.cairo +72 -0
  234. package/layerzero/src/treasury/errors.cairo +22 -0
  235. package/layerzero/src/treasury/events.cairo +5 -0
  236. package/layerzero/src/treasury/interfaces/layerzero_treasury.cairo +54 -0
  237. package/layerzero/src/treasury/interfaces/lz_token_fee_lib.cairo +45 -0
  238. package/layerzero/src/treasury/interfaces/treasury_admin.cairo +39 -0
  239. package/layerzero/src/treasury/treasury.cairo +140 -0
  240. package/layerzero/src/workers/access_control.cairo +11 -0
  241. package/layerzero/src/workers/base/base.cairo +238 -0
  242. package/layerzero/src/workers/base/errors.cairo +24 -0
  243. package/layerzero/src/workers/base/events.cairo +43 -0
  244. package/layerzero/src/workers/base/interface.cairo +93 -0
  245. package/layerzero/src/workers/base/structs.cairo +10 -0
  246. package/layerzero/src/workers/common.cairo +59 -0
  247. package/layerzero/src/workers/dvn/constants.cairo +11 -0
  248. package/layerzero/src/workers/dvn/dvn.cairo +338 -0
  249. package/layerzero/src/workers/dvn/errors.cairo +80 -0
  250. package/layerzero/src/workers/dvn/events.cairo +30 -0
  251. package/layerzero/src/workers/dvn/fee_lib/dvn_fee_lib.cairo +152 -0
  252. package/layerzero/src/workers/dvn/fee_lib/interface.cairo +45 -0
  253. package/layerzero/src/workers/dvn/interface.cairo +131 -0
  254. package/layerzero/src/workers/dvn/options.cairo +125 -0
  255. package/layerzero/src/workers/dvn/structs.cairo +51 -0
  256. package/layerzero/src/workers/executor/errors.cairo +159 -0
  257. package/layerzero/src/workers/executor/events.cairo +32 -0
  258. package/layerzero/src/workers/executor/executor.cairo +392 -0
  259. package/layerzero/src/workers/executor/fee_lib/executor_fee_lib.cairo +160 -0
  260. package/layerzero/src/workers/executor/fee_lib/interface.cairo +87 -0
  261. package/layerzero/src/workers/executor/interface.cairo +131 -0
  262. package/layerzero/src/workers/executor/options.cairo +244 -0
  263. package/layerzero/src/workers/executor/structs.cairo +119 -0
  264. package/layerzero/src/workers/interface.cairo +32 -0
  265. package/layerzero/src/workers/price_feed/constants.cairo +7 -0
  266. package/layerzero/src/workers/price_feed/errors.cairo +28 -0
  267. package/layerzero/src/workers/price_feed/events.cairo +13 -0
  268. package/layerzero/src/workers/price_feed/interface.cairo +264 -0
  269. package/layerzero/src/workers/price_feed/price_feed.cairo +392 -0
  270. package/layerzero/src/workers/price_feed/structs.cairo +74 -0
  271. package/layerzero/tests/common/test_constants.cairo +21 -0
  272. package/layerzero/tests/common/test_guid.cairo +232 -0
  273. package/layerzero/tests/common/test_packet_v1_codec.cairo +372 -0
  274. package/layerzero/tests/common/utils.cairo +23 -0
  275. package/layerzero/tests/e2e/oft_utils.cairo +121 -0
  276. package/layerzero/tests/e2e/test_counter_with_sml.cairo +194 -0
  277. package/layerzero/tests/e2e/test_counter_with_uln.cairo +352 -0
  278. package/layerzero/tests/e2e/test_dvn.cairo +406 -0
  279. package/layerzero/tests/e2e/test_lz_token.cairo +354 -0
  280. package/layerzero/tests/e2e/test_oft_compose_with_uln.cairo +364 -0
  281. package/layerzero/tests/e2e/test_oft_with_sml.cairo +240 -0
  282. package/layerzero/tests/e2e/test_oft_with_uln.cairo +299 -0
  283. package/layerzero/tests/e2e/utils.cairo +490 -0
  284. package/layerzero/tests/endpoint/message_lib_manager/test_message_lib_manager.cairo +2051 -0
  285. package/layerzero/tests/endpoint/message_lib_manager/utils.cairo +45 -0
  286. package/layerzero/tests/endpoint/messaging_channel/test_messaging_channel.cairo +621 -0
  287. package/layerzero/tests/endpoint/messaging_channel/utils.cairo +96 -0
  288. package/layerzero/tests/endpoint/messaging_composer/test_messaging_composer.cairo +456 -0
  289. package/layerzero/tests/endpoint/messaging_composer/utils.cairo +75 -0
  290. package/layerzero/tests/endpoint/test_endpoint_commit.cairo +763 -0
  291. package/layerzero/tests/endpoint/test_endpoint_lzreceive.cairo +1253 -0
  292. package/layerzero/tests/endpoint/test_endpoint_quote.cairo +71 -0
  293. package/layerzero/tests/endpoint/test_endpoint_send.cairo +1327 -0
  294. package/layerzero/tests/endpoint/utils.cairo +129 -0
  295. package/layerzero/tests/fuzzable/blockchain_config.cairo +89 -0
  296. package/layerzero/tests/fuzzable/bytes32.cairo +16 -0
  297. package/layerzero/tests/fuzzable/contract_address.cairo +67 -0
  298. package/layerzero/tests/fuzzable/dst_config.cairo +37 -0
  299. package/layerzero/tests/fuzzable/eid.cairo +23 -0
  300. package/layerzero/tests/fuzzable/eth_address.cairo +17 -0
  301. package/layerzero/tests/fuzzable/expiry.cairo +27 -0
  302. package/layerzero/tests/fuzzable/felt_array.cairo +38 -0
  303. package/layerzero/tests/fuzzable/inbound_params.cairo +21 -0
  304. package/layerzero/tests/fuzzable/keys.cairo +16 -0
  305. package/layerzero/tests/fuzzable/model_type.cairo +27 -0
  306. package/layerzero/tests/fuzzable/origin.cairo +21 -0
  307. package/layerzero/tests/fuzzable/price.cairo +32 -0
  308. package/layerzero/tests/fuzzable/role_admin.cairo +29 -0
  309. package/layerzero/tests/fuzzable/small_byte_array.cairo +61 -0
  310. package/layerzero/tests/lib.cairo +177 -0
  311. package/layerzero/tests/message_lib/sml/test_simple_message_lib.cairo +224 -0
  312. package/layerzero/tests/message_lib/uln/test_uln_admin.cairo +2150 -0
  313. package/layerzero/tests/message_lib/uln/test_uln_config.cairo +527 -0
  314. package/layerzero/tests/message_lib/uln/test_uln_config_storage_node.cairo +69 -0
  315. package/layerzero/tests/message_lib/uln/test_uln_executor_config.cairo +173 -0
  316. package/layerzero/tests/message_lib/uln/test_uln_options.cairo +329 -0
  317. package/layerzero/tests/message_lib/uln/test_uln_quote.cairo +1038 -0
  318. package/layerzero/tests/message_lib/uln/test_uln_receive.cairo +715 -0
  319. package/layerzero/tests/message_lib/uln/test_uln_send.cairo +1155 -0
  320. package/layerzero/tests/message_lib/uln/utils.cairo +59 -0
  321. package/layerzero/tests/mocks/composer_target.cairo +76 -0
  322. package/layerzero/tests/mocks/endpoint.cairo +199 -0
  323. package/layerzero/tests/mocks/erc20/erc20.cairo +50 -0
  324. package/layerzero/tests/mocks/erc20/interface.cairo +8 -0
  325. package/layerzero/tests/mocks/message_inspector/message_inspector.cairo +17 -0
  326. package/layerzero/tests/mocks/message_lib_manager.cairo +98 -0
  327. package/layerzero/tests/mocks/messaging_channel/interface.cairo +23 -0
  328. package/layerzero/tests/mocks/messaging_channel/messaging_channel.cairo +138 -0
  329. package/layerzero/tests/mocks/messaging_composer.cairo +171 -0
  330. package/layerzero/tests/mocks/oapp_core/interface.cairo +53 -0
  331. package/layerzero/tests/mocks/oapp_core/oapp_core.cairo +142 -0
  332. package/layerzero/tests/mocks/oapp_options_type3.cairo +42 -0
  333. package/layerzero/tests/mocks/oft_core/interface.cairo +28 -0
  334. package/layerzero/tests/mocks/oft_core/oft_core.cairo +242 -0
  335. package/layerzero/tests/mocks/receiver.cairo +54 -0
  336. package/layerzero/tests/mocks/treasury/lz_token_fee_lib.cairo +57 -0
  337. package/layerzero/tests/mocks/treasury/treasury.cairo +74 -0
  338. package/layerzero/tests/mocks/uln_config/interface.cairo +12 -0
  339. package/layerzero/tests/mocks/uln_config/uln_config.cairo +35 -0
  340. package/layerzero/tests/mocks/workers/base.cairo +80 -0
  341. package/layerzero/tests/mocks/workers/dvn.cairo +115 -0
  342. package/layerzero/tests/mocks/workers/executor/decode/decode.cairo +97 -0
  343. package/layerzero/tests/mocks/workers/executor/decode/interface.cairo +59 -0
  344. package/layerzero/tests/mocks/workers/executor/executor.cairo +176 -0
  345. package/layerzero/tests/oapps/common/test_oapp_options_type_3.cairo +279 -0
  346. package/layerzero/tests/oapps/oft/test_oft_adapter.cairo +441 -0
  347. package/layerzero/tests/oapps/oft/test_oft_compose_msg_codec.cairo +139 -0
  348. package/layerzero/tests/oapps/oft/test_oft_core.cairo +751 -0
  349. package/layerzero/tests/oapps/oft/test_oft_msg_codec.cairo +268 -0
  350. package/layerzero/tests/oapps/test_counter.cairo +470 -0
  351. package/layerzero/tests/oapps/test_oapp_core.cairo +750 -0
  352. package/layerzero/tests/treasury/test_lz_token_fee_lib.cairo +63 -0
  353. package/layerzero/tests/treasury/test_treasury.cairo +458 -0
  354. package/layerzero/tests/treasury/utils.cairo +8 -0
  355. package/layerzero/tests/utils.cairo +48 -0
  356. package/layerzero/tests/workers/base/test_worker_base.cairo +1097 -0
  357. package/layerzero/tests/workers/base/utils.cairo +76 -0
  358. package/layerzero/tests/workers/dvn/fee_lib/test_dvn_fee_lib.cairo +361 -0
  359. package/layerzero/tests/workers/dvn/test_dvn.cairo +1101 -0
  360. package/layerzero/tests/workers/dvn/test_dvn_options.cairo +312 -0
  361. package/layerzero/tests/workers/dvn/utils.cairo +236 -0
  362. package/layerzero/tests/workers/executor/fee_lib/test_executor_fee_lib.cairo +223 -0
  363. package/layerzero/tests/workers/executor/test_decode.cairo +612 -0
  364. package/layerzero/tests/workers/executor/test_executor.cairo +1472 -0
  365. package/layerzero/tests/workers/executor/utils.cairo +296 -0
  366. package/layerzero/tests/workers/price_feed/test_price_feed.cairo +879 -0
  367. package/layerzero/tests/workers/price_feed/utils.cairo +37 -0
  368. package/libs/enumerable_set/Scarb.lock +24 -0
  369. package/libs/enumerable_set/Scarb.toml +17 -0
  370. package/libs/enumerable_set/src/enumerable_set.cairo +118 -0
  371. package/libs/enumerable_set/src/lib.cairo +4 -0
  372. package/libs/enumerable_set/tests/lib.cairo +5 -0
  373. package/libs/enumerable_set/tests/mocks/mock_enumerable_set.cairo +61 -0
  374. package/libs/enumerable_set/tests/test_enumerable_set.cairo +379 -0
  375. package/libs/lz_utils/Scarb.lock +24 -0
  376. package/libs/lz_utils/Scarb.toml +17 -0
  377. package/libs/lz_utils/src/bytes.cairo +33 -0
  378. package/libs/lz_utils/src/error.cairo +12 -0
  379. package/libs/lz_utils/src/keccak.cairo +28 -0
  380. package/libs/lz_utils/src/lib.cairo +3 -0
  381. package/libs/multisig/Scarb.lock +172 -0
  382. package/libs/multisig/Scarb.toml +23 -0
  383. package/libs/multisig/src/errors.cairo +84 -0
  384. package/libs/multisig/src/events.cairo +13 -0
  385. package/libs/multisig/src/interface.cairo +73 -0
  386. package/libs/multisig/src/lib.cairo +7 -0
  387. package/libs/multisig/src/multisig.cairo +241 -0
  388. package/libs/multisig/tests/lib.cairo +4 -0
  389. package/libs/multisig/tests/mocks/mock_multisig.cairo +57 -0
  390. package/libs/multisig/tests/test_multisig.cairo +452 -0
  391. package/package.json +41 -0
  392. package/src/scripts/build-abi.ts +51 -0
  393. package/target/CACHEDIR.TAG +3 -0
  394. package/target/dev/.fingerprint/alexandria_bytes-5ea6u5t70d7qi/alexandria_bytes +1 -0
  395. package/target/dev/.fingerprint/alexandria_data_structures-0aue3g6q80gs0/alexandria_data_structures +1 -0
  396. package/target/dev/.fingerprint/alexandria_math-h2fi7jdq4isuu/alexandria_math +1 -0
  397. package/target/dev/.fingerprint/core-lq3u730l5p1ag/core +1 -0
  398. package/target/dev/.fingerprint/core-vf7fc6rvic5vi/core +1 -0
  399. package/target/dev/.fingerprint/enumerable_set-eaerkg8njl85o/enumerable_set +1 -0
  400. package/target/dev/.fingerprint/enumerable_set-r54oje7t06ku8/enumerable_set +1 -0
  401. package/target/dev/.fingerprint/layerzero-oqgdqsaddpi2k/layerzero +1 -0
  402. package/target/dev/.fingerprint/lz_utils-kfkkeueiqg0pa/lz_utils +1 -0
  403. package/target/dev/.fingerprint/lz_utils-u4v1os6e7gkng/lz_utils +1 -0
  404. package/target/dev/.fingerprint/multisig-0fjetugejecge/multisig +1 -0
  405. package/target/dev/.fingerprint/multisig-6j5kqs436hm54/multisig +1 -0
  406. package/target/dev/.fingerprint/openzeppelin-ei1id1hu088lo/openzeppelin +1 -0
  407. package/target/dev/.fingerprint/openzeppelin-j9d5nd1qhfnu6/openzeppelin +1 -0
  408. package/target/dev/.fingerprint/openzeppelin_access-3oa41aikpaek0/openzeppelin_access +1 -0
  409. package/target/dev/.fingerprint/openzeppelin_access-p5h849v8so76q/openzeppelin_access +1 -0
  410. package/target/dev/.fingerprint/openzeppelin_account-4qhv5fks84g9u/openzeppelin_account +1 -0
  411. package/target/dev/.fingerprint/openzeppelin_account-hgbm8ln9ah7rm/openzeppelin_account +1 -0
  412. package/target/dev/.fingerprint/openzeppelin_finance-n70q9al0cps8i/openzeppelin_finance +1 -0
  413. package/target/dev/.fingerprint/openzeppelin_finance-nnd4f8703t3ak/openzeppelin_finance +1 -0
  414. package/target/dev/.fingerprint/openzeppelin_governance-3gnk21ubp5lis/openzeppelin_governance +1 -0
  415. package/target/dev/.fingerprint/openzeppelin_governance-rj1bfont4fij4/openzeppelin_governance +1 -0
  416. package/target/dev/.fingerprint/openzeppelin_introspection-3fja9hd1gvbcq/openzeppelin_introspection +1 -0
  417. package/target/dev/.fingerprint/openzeppelin_introspection-jc3nf5525eet6/openzeppelin_introspection +1 -0
  418. package/target/dev/.fingerprint/openzeppelin_merkle_tree-4en77ogr2r2l2/openzeppelin_merkle_tree +1 -0
  419. package/target/dev/.fingerprint/openzeppelin_merkle_tree-4t190frqs4db8/openzeppelin_merkle_tree +1 -0
  420. package/target/dev/.fingerprint/openzeppelin_presets-aqb0f6p9c0bp6/openzeppelin_presets +1 -0
  421. package/target/dev/.fingerprint/openzeppelin_presets-nseg8korhin8e/openzeppelin_presets +1 -0
  422. package/target/dev/.fingerprint/openzeppelin_security-g7p73ji1ih1qg/openzeppelin_security +1 -0
  423. package/target/dev/.fingerprint/openzeppelin_security-qp5328v80452u/openzeppelin_security +1 -0
  424. package/target/dev/.fingerprint/openzeppelin_token-jjf7tl9rphc6k/openzeppelin_token +1 -0
  425. package/target/dev/.fingerprint/openzeppelin_token-r6s43vlpj6rqk/openzeppelin_token +1 -0
  426. package/target/dev/.fingerprint/openzeppelin_upgrades-0dpbnre7engca/openzeppelin_upgrades +1 -0
  427. package/target/dev/.fingerprint/openzeppelin_upgrades-2sqgvbuv9s800/openzeppelin_upgrades +1 -0
  428. package/target/dev/.fingerprint/openzeppelin_utils-mj395ivff1ffo/openzeppelin_utils +1 -0
  429. package/target/dev/.fingerprint/openzeppelin_utils-oh1hse8sjumgm/openzeppelin_utils +1 -0
  430. package/target/dev/.fingerprint/starkware_utils-1qnnjnq0pf9u0/starkware_utils +1 -0
  431. package/target/dev/.fingerprint/starkware_utils-mh8e3te65lju4/starkware_utils +1 -0
  432. package/target/dev/enumerable_set.sierra.json +1 -0
  433. package/target/dev/incremental/alexandria_bytes-5ea6u5t70d7qi.bin +0 -0
  434. package/target/dev/incremental/alexandria_data_structures-0aue3g6q80gs0.bin +0 -0
  435. package/target/dev/incremental/alexandria_math-h2fi7jdq4isuu.bin +0 -0
  436. package/target/dev/incremental/core-lq3u730l5p1ag.bin +0 -0
  437. package/target/dev/incremental/core-vf7fc6rvic5vi.bin +0 -0
  438. package/target/dev/incremental/enumerable_set-eaerkg8njl85o.bin +0 -0
  439. package/target/dev/incremental/enumerable_set-r54oje7t06ku8.bin +0 -0
  440. package/target/dev/incremental/layerzero-oqgdqsaddpi2k.bin +0 -0
  441. package/target/dev/incremental/lz_utils-kfkkeueiqg0pa.bin +0 -0
  442. package/target/dev/incremental/lz_utils-u4v1os6e7gkng.bin +0 -0
  443. package/target/dev/incremental/multisig-0fjetugejecge.bin +0 -0
  444. package/target/dev/incremental/multisig-6j5kqs436hm54.bin +0 -0
  445. package/target/dev/incremental/openzeppelin-ei1id1hu088lo.bin +0 -0
  446. package/target/dev/incremental/openzeppelin-j9d5nd1qhfnu6.bin +0 -0
  447. package/target/dev/incremental/openzeppelin_access-3oa41aikpaek0.bin +0 -0
  448. package/target/dev/incremental/openzeppelin_access-p5h849v8so76q.bin +0 -0
  449. package/target/dev/incremental/openzeppelin_account-4qhv5fks84g9u.bin +0 -0
  450. package/target/dev/incremental/openzeppelin_account-hgbm8ln9ah7rm.bin +0 -0
  451. package/target/dev/incremental/openzeppelin_finance-n70q9al0cps8i.bin +0 -0
  452. package/target/dev/incremental/openzeppelin_finance-nnd4f8703t3ak.bin +0 -0
  453. package/target/dev/incremental/openzeppelin_governance-3gnk21ubp5lis.bin +0 -0
  454. package/target/dev/incremental/openzeppelin_governance-rj1bfont4fij4.bin +0 -0
  455. package/target/dev/incremental/openzeppelin_introspection-3fja9hd1gvbcq.bin +0 -0
  456. package/target/dev/incremental/openzeppelin_introspection-jc3nf5525eet6.bin +0 -0
  457. package/target/dev/incremental/openzeppelin_merkle_tree-4en77ogr2r2l2.bin +0 -0
  458. package/target/dev/incremental/openzeppelin_merkle_tree-4t190frqs4db8.bin +0 -0
  459. package/target/dev/incremental/openzeppelin_presets-aqb0f6p9c0bp6.bin +0 -0
  460. package/target/dev/incremental/openzeppelin_presets-nseg8korhin8e.bin +0 -0
  461. package/target/dev/incremental/openzeppelin_security-g7p73ji1ih1qg.bin +0 -0
  462. package/target/dev/incremental/openzeppelin_security-qp5328v80452u.bin +0 -0
  463. package/target/dev/incremental/openzeppelin_token-jjf7tl9rphc6k.bin +0 -0
  464. package/target/dev/incremental/openzeppelin_token-r6s43vlpj6rqk.bin +0 -0
  465. package/target/dev/incremental/openzeppelin_upgrades-0dpbnre7engca.bin +0 -0
  466. package/target/dev/incremental/openzeppelin_upgrades-2sqgvbuv9s800.bin +0 -0
  467. package/target/dev/incremental/openzeppelin_utils-mj395ivff1ffo.bin +0 -0
  468. package/target/dev/incremental/openzeppelin_utils-oh1hse8sjumgm.bin +0 -0
  469. package/target/dev/incremental/starkware_utils-1qnnjnq0pf9u0.bin +0 -0
  470. package/target/dev/incremental/starkware_utils-mh8e3te65lju4.bin +0 -0
  471. package/target/dev/layerzero.starknet_artifacts.json +1 -0
  472. package/target/dev/layerzero_BlockedMessageLib.compiled_contract_class.json +1 -0
  473. package/target/dev/layerzero_BlockedMessageLib.contract_class.json +1 -0
  474. package/target/dev/layerzero_Dvn.compiled_contract_class.json +1 -0
  475. package/target/dev/layerzero_Dvn.contract_class.json +1 -0
  476. package/target/dev/layerzero_DvnFeeLib.compiled_contract_class.json +1 -0
  477. package/target/dev/layerzero_DvnFeeLib.contract_class.json +1 -0
  478. package/target/dev/layerzero_Endpoint.compiled_contract_class.json +1 -0
  479. package/target/dev/layerzero_Endpoint.contract_class.json +1 -0
  480. package/target/dev/layerzero_Executor.compiled_contract_class.json +1 -0
  481. package/target/dev/layerzero_Executor.contract_class.json +1 -0
  482. package/target/dev/layerzero_ExecutorFeeLib.compiled_contract_class.json +1 -0
  483. package/target/dev/layerzero_ExecutorFeeLib.contract_class.json +1 -0
  484. package/target/dev/layerzero_OApp.compiled_contract_class.json +1 -0
  485. package/target/dev/layerzero_OApp.contract_class.json +1 -0
  486. package/target/dev/layerzero_OFT.compiled_contract_class.json +1 -0
  487. package/target/dev/layerzero_OFT.contract_class.json +1 -0
  488. package/target/dev/layerzero_OFTAdapter.compiled_contract_class.json +1 -0
  489. package/target/dev/layerzero_OFTAdapter.contract_class.json +1 -0
  490. package/target/dev/layerzero_OmniCounter.compiled_contract_class.json +1 -0
  491. package/target/dev/layerzero_OmniCounter.contract_class.json +1 -0
  492. package/target/dev/layerzero_PriceFeed.compiled_contract_class.json +1 -0
  493. package/target/dev/layerzero_PriceFeed.contract_class.json +1 -0
  494. package/target/dev/layerzero_SimpleMessageLib.compiled_contract_class.json +1 -0
  495. package/target/dev/layerzero_SimpleMessageLib.contract_class.json +1 -0
  496. package/target/dev/layerzero_Treasury.compiled_contract_class.json +1 -0
  497. package/target/dev/layerzero_Treasury.contract_class.json +1 -0
  498. package/target/dev/layerzero_UltraLightNode.compiled_contract_class.json +1 -0
  499. package/target/dev/layerzero_UltraLightNode.contract_class.json +1 -0
  500. package/target/dev/lz_utils.sierra.json +1 -0
  501. package/target/dev/multisig.sierra.json +1 -0
  502. package/tools/update_contracts.sh +19 -0
  503. package/tsconfig.json +20 -0
  504. package/tsup.config.ts +7 -0
@@ -0,0 +1,1155 @@
1
+ //! ULN send tests
2
+
3
+ use alexandria_bytes::byte_array_ext::ByteArrayTraitExt;
4
+ use layerzero::common::constants::ZERO_ADDRESS;
5
+ use layerzero::common::packet_v1_codec::PacketV1Codec;
6
+ use layerzero::common::structs::messaging::{MessageLibSendResult, Payee};
7
+ use layerzero::common::structs::packet::{Packet, PacketHeader};
8
+ use layerzero::message_lib::interface::{
9
+ IMessageLibDispatcher, IMessageLibDispatcherTrait, IMessageLibSafeDispatcher,
10
+ IMessageLibSafeDispatcherTrait,
11
+ };
12
+ use layerzero::message_lib::uln::errors::{
13
+ err_caller_not_endpoint, err_message_too_large, err_must_have_at_least_one_dvn,
14
+ };
15
+ use layerzero::message_lib::uln::events::{DvnFeesPaid, ExecutorFeePaid, TreasuryFeePaid};
16
+ use layerzero::message_lib::uln::interface::{
17
+ IUltraLightNodeAdminDispatcher, IUltraLightNodeAdminDispatcherTrait,
18
+ };
19
+ use layerzero::message_lib::uln::options::TYPE_3;
20
+ use layerzero::message_lib::uln::structs::executor_config::ExecutorConfig;
21
+ use layerzero::message_lib::uln::structs::uln_config::{SetDefaultUlnConfigParam, UlnConfig};
22
+ use layerzero::message_lib::uln::ultra_light_node::UltraLightNode;
23
+ use layerzero::workers::dvn::options::DVN_WORKER_ID;
24
+ use layerzero::workers::executor::options::EXECUTOR_WORKER_ID;
25
+ use lz_utils::bytes::Bytes32;
26
+ use snforge_std::{
27
+ ContractClassTrait, DeclareResultTrait, EventSpyAssertionsTrait, declare, spy_events,
28
+ start_cheat_caller_address, stop_cheat_caller_address,
29
+ };
30
+ use starknet::ContractAddress;
31
+ use starkware_utils_testing::test_utils::assert_panic_with_error;
32
+ use crate::common::test_guid::MAX_U256;
33
+ use crate::common::utils::total_native_fee_from_receipt;
34
+
35
+ // Import shared test utils
36
+ use crate::message_lib::uln::utils::{
37
+ set_oapp_executor_send_config_via_message_lib, set_oapp_uln_send_config_via_message_lib,
38
+ };
39
+ use crate::mocks::treasury::treasury::MockTreasury::{
40
+ IMockTreasuryHelpersDispatcher, IMockTreasuryHelpersDispatcherTrait,
41
+ };
42
+ use crate::mocks::workers::dvn::MockDVN::{
43
+ IMockDVNHelpersDispatcher, IMockDVNHelpersDispatcherTrait,
44
+ };
45
+ use crate::mocks::workers::executor::executor::MockExecutor::{
46
+ IMockExecutorHelpersDispatcher, IMockExecutorHelpersDispatcherTrait,
47
+ };
48
+ use crate::utils::sort_contract_addresses;
49
+
50
+ // Test constants
51
+ pub const OWNER: ContractAddress = 'owner'.try_into().unwrap();
52
+ pub const ENDPOINT: ContractAddress = 'endpoint'.try_into().unwrap();
53
+ pub const NON_ENDPOINT: ContractAddress = 'non_endpoint'.try_into().unwrap();
54
+ pub const SENDER: ContractAddress = 'sender'.try_into().unwrap();
55
+ pub const RECEIVER: ContractAddress = 'receiver'.try_into().unwrap();
56
+ pub const DVN_1: ContractAddress = 'dvn_1'.try_into().unwrap();
57
+ pub const DVN_2: ContractAddress = 'dvn_2'.try_into().unwrap();
58
+ pub const DVN_3: ContractAddress = 'dvn_3'.try_into().unwrap();
59
+ pub const EXECUTOR: ContractAddress = 'executor'.try_into().unwrap();
60
+ pub const DST_EID: u32 = 2;
61
+ pub const SRC_EID: u32 = 1;
62
+ pub const MAX_MESSAGE_SIZE: u32 = 1000;
63
+ pub const CONFIRMATIONS: u64 = 20;
64
+ pub const TREASURY_NATIVE_FEE_CAP: u256 = 200;
65
+
66
+ // Fee constants
67
+ pub const DVN_FEE: u256 = 1000;
68
+ pub const DVN_FEE_2: u256 = 1500;
69
+ pub const DVN_FEE_OPTIONAL_1: u256 = 800;
70
+ pub const DVN_FEE_OPTIONAL_2: u256 = 900;
71
+ pub const EXECUTOR_FEE: u256 = 2000;
72
+ pub const TREASURY_FEE: u256 = 50; // Below cap to test normal operation
73
+ pub const TREASURY_FEE_AT_CAP: u256 = 200; // At cap
74
+ pub const TREASURY_FEE_ABOVE_CAP: u256 = 500; // Above cap to test capping
75
+ pub const ZERO_FEE: u256 = 0;
76
+
77
+ // Helper functions
78
+ fn deploy_ultra_light_node(
79
+ treasury_fee: u256,
80
+ ) -> (
81
+ IMessageLibDispatcher,
82
+ IMessageLibSafeDispatcher,
83
+ IUltraLightNodeAdminDispatcher,
84
+ ContractAddress,
85
+ ContractAddress,
86
+ ) {
87
+ let contract = declare("UltraLightNode").unwrap().contract_class();
88
+ let treasury = deploy_mock_treasury(treasury_fee);
89
+ let mut constructor_calldata = array![OWNER.into(), treasury.into(), ENDPOINT.into()];
90
+ TREASURY_NATIVE_FEE_CAP.serialize(ref constructor_calldata);
91
+ let (contract_address, _) = contract.deploy(@constructor_calldata).unwrap();
92
+
93
+ let message_lib = IMessageLibDispatcher { contract_address };
94
+ let message_lib_safe = IMessageLibSafeDispatcher { contract_address };
95
+ let admin = IUltraLightNodeAdminDispatcher { contract_address };
96
+
97
+ (message_lib, message_lib_safe, admin, contract_address, treasury)
98
+ }
99
+
100
+ fn deploy_mock_treasury(treasury_fee: u256) -> ContractAddress {
101
+ let contract = declare("MockTreasury").unwrap().contract_class();
102
+ let constructor_calldata = array![treasury_fee.low.into(), treasury_fee.high.into()];
103
+ let (address, _) = contract.deploy(@constructor_calldata).unwrap();
104
+ address
105
+ }
106
+
107
+ fn deploy_mock_dvn(fee: u256) -> ContractAddress {
108
+ let contract = declare("MockDVN").unwrap().contract_class();
109
+ let constructor_calldata = array![fee.low.into(), fee.high.into()];
110
+ let (address, _) = contract.deploy(@constructor_calldata).unwrap();
111
+ address
112
+ }
113
+
114
+ fn deploy_mock_executor(fee: u256) -> ContractAddress {
115
+ let contract = declare("MockExecutor").unwrap().contract_class();
116
+ let constructor_calldata = array![
117
+ fee.low.into(), fee.high.into(), ZERO_ADDRESS.into(), ZERO_ADDRESS.into(),
118
+ ZERO_ADDRESS.into(),
119
+ ];
120
+ let (address, _) = contract.deploy(@constructor_calldata).unwrap();
121
+ address
122
+ }
123
+
124
+ fn create_test_uln_config(
125
+ required_dvns: Array<ContractAddress>,
126
+ optional_dvns: Array<ContractAddress>,
127
+ optional_threshold: u8,
128
+ ) -> UlnConfig {
129
+ UlnConfig {
130
+ confirmations: CONFIRMATIONS,
131
+ has_confirmations: true,
132
+ required_dvns,
133
+ has_required_dvns: true,
134
+ optional_dvns,
135
+ optional_dvn_threshold: optional_threshold,
136
+ has_optional_dvns: true,
137
+ }
138
+ }
139
+
140
+ fn create_test_executor_config(executor_address: ContractAddress) -> ExecutorConfig {
141
+ ExecutorConfig { max_message_size: MAX_MESSAGE_SIZE, executor: executor_address }
142
+ }
143
+
144
+ fn create_test_packet() -> Packet {
145
+ Packet {
146
+ nonce: 1,
147
+ src_eid: SRC_EID,
148
+ sender: SENDER,
149
+ dst_eid: DST_EID,
150
+ receiver: RECEIVER.into(),
151
+ guid: Bytes32 { value: 'test_guid'.into() },
152
+ message: "test message",
153
+ }
154
+ }
155
+
156
+ fn create_empty_options() -> ByteArray {
157
+ let mut options: ByteArray = Default::default();
158
+ options.append_u16(TYPE_3);
159
+ options
160
+ }
161
+
162
+ fn create_packet_header_from_packet(packet: @Packet) -> PacketHeader {
163
+ PacketHeader {
164
+ nonce: *packet.nonce,
165
+ src_eid: *packet.src_eid,
166
+ sender: *packet.sender,
167
+ dst_eid: *packet.dst_eid,
168
+ receiver: *packet.receiver,
169
+ }
170
+ }
171
+
172
+
173
+ fn setup_default_config_with_mocks(
174
+ admin: IUltraLightNodeAdminDispatcher,
175
+ contract_address: ContractAddress,
176
+ dst_eid: u32,
177
+ required_dvns: Array<ContractAddress>,
178
+ optional_dvns: Array<ContractAddress>,
179
+ optional_threshold: u8,
180
+ executor_address: ContractAddress,
181
+ ) {
182
+ start_cheat_caller_address(contract_address, OWNER);
183
+
184
+ // Set default ULN config
185
+ let default_config = create_test_uln_config(required_dvns, optional_dvns, optional_threshold);
186
+ let config_params = array![SetDefaultUlnConfigParam { eid: dst_eid, config: default_config }];
187
+ admin.set_default_uln_send_config(config_params);
188
+
189
+ // Set default executor config
190
+ let executor_config = create_test_executor_config(executor_address);
191
+ admin.set_default_executor_config(dst_eid, executor_config);
192
+
193
+ stop_cheat_caller_address(contract_address);
194
+ }
195
+
196
+ // Test cases for send function
197
+ #[test]
198
+ fn test_send_with_single_required_dvn() {
199
+ let (message_lib, _, admin, contract_address, treasury) = deploy_ultra_light_node(TREASURY_FEE);
200
+ let dvn_address = deploy_mock_dvn(DVN_FEE);
201
+ let executor_address = deploy_mock_executor(EXECUTOR_FEE);
202
+
203
+ // Setup default config
204
+ setup_default_config_with_mocks(
205
+ admin, contract_address, DST_EID, array![dvn_address], array![], 0, executor_address,
206
+ );
207
+
208
+ let packet = create_test_packet();
209
+ let options = create_empty_options();
210
+
211
+ // Set up event spy
212
+ let mut spy = spy_events();
213
+
214
+ // Call send as endpoint
215
+ start_cheat_caller_address(contract_address, ENDPOINT);
216
+ let MessageLibSendResult {
217
+ message_receipt, encoded_packet,
218
+ } = message_lib.send(packet.clone(), options, false);
219
+ stop_cheat_caller_address(contract_address);
220
+
221
+ // Verify receipt
222
+ assert(message_receipt.guid == packet.guid, 'incorrect guid');
223
+ assert(message_receipt.nonce == packet.nonce, 'incorrect nonce');
224
+ assert(
225
+ total_native_fee_from_receipt(@message_receipt) == DVN_FEE + EXECUTOR_FEE + TREASURY_FEE,
226
+ 'incorrect total fee',
227
+ );
228
+ assert(message_receipt.payees.len() == 3, 'incorrect payees count');
229
+
230
+ // Verify payees
231
+ let dvn_payee = message_receipt.payees.at(0);
232
+ assert(*dvn_payee.receiver == dvn_address, 'incorrect dvn payee receiver');
233
+ assert(*dvn_payee.native_amount == DVN_FEE, 'incorrect dvn payee amount');
234
+
235
+ let executor_payee = message_receipt.payees.at(1);
236
+ assert(*executor_payee.receiver == executor_address, 'inc executor payee receiver');
237
+ assert(*executor_payee.native_amount == EXECUTOR_FEE, 'incorrect executor payee amount');
238
+
239
+ let treasury_payee = message_receipt.payees.at(2);
240
+ assert(*treasury_payee.receiver == treasury, 'inc treasury payee receiver');
241
+ assert(*treasury_payee.native_amount == TREASURY_FEE, 'incorrect treasury payee amount');
242
+
243
+ // Verify encoded packet is not empty
244
+ assert(encoded_packet.len() > 0, 'encoded packet is empty');
245
+
246
+ // Verify events were emitted
247
+ let packet_header = create_packet_header_from_packet(@packet);
248
+ spy
249
+ .assert_emitted(
250
+ @array![
251
+ (
252
+ contract_address,
253
+ UltraLightNode::Event::DvnFeesPaid(
254
+ DvnFeesPaid {
255
+ oapp: SENDER,
256
+ payees: array![
257
+ Payee {
258
+ receiver: dvn_address,
259
+ native_amount: DVN_FEE,
260
+ lz_token_amount: 0,
261
+ },
262
+ ],
263
+ packet_header: packet_header.clone(),
264
+ },
265
+ ),
266
+ ),
267
+ (
268
+ contract_address,
269
+ UltraLightNode::Event::ExecutorFeePaid(
270
+ ExecutorFeePaid {
271
+ oapp: SENDER,
272
+ payee: Payee {
273
+ receiver: executor_address,
274
+ native_amount: EXECUTOR_FEE,
275
+ lz_token_amount: 0,
276
+ },
277
+ packet_header: packet_header.clone(),
278
+ },
279
+ ),
280
+ ),
281
+ (
282
+ contract_address,
283
+ UltraLightNode::Event::TreasuryFeePaid(
284
+ TreasuryFeePaid {
285
+ oapp: SENDER,
286
+ payee: Payee {
287
+ receiver: treasury, native_amount: TREASURY_FEE, lz_token_amount: 0,
288
+ },
289
+ packet_header: packet_header.clone(),
290
+ },
291
+ ),
292
+ ),
293
+ ],
294
+ );
295
+ }
296
+
297
+ #[test]
298
+ fn test_send_with_multiple_required_dvns() {
299
+ let (message_lib, _, admin, contract_address, _) = deploy_ultra_light_node(TREASURY_FEE);
300
+ let dvn1_address = deploy_mock_dvn(DVN_FEE);
301
+ let dvn2_address = deploy_mock_dvn(DVN_FEE_2);
302
+ let executor_address = deploy_mock_executor(EXECUTOR_FEE);
303
+
304
+ // Setup default config
305
+ setup_default_config_with_mocks(
306
+ admin,
307
+ contract_address,
308
+ DST_EID,
309
+ sort_contract_addresses(array![dvn1_address, dvn2_address]),
310
+ array![],
311
+ 0,
312
+ executor_address,
313
+ );
314
+
315
+ let packet = create_test_packet();
316
+ let options = create_empty_options();
317
+
318
+ // Set up event spy
319
+ let mut spy = spy_events();
320
+
321
+ // Call send as endpoint
322
+ start_cheat_caller_address(contract_address, ENDPOINT);
323
+ let MessageLibSendResult {
324
+ message_receipt, ..,
325
+ } = message_lib.send(packet.clone(), options, false);
326
+ stop_cheat_caller_address(contract_address);
327
+
328
+ // Verify receipt
329
+ let expected_total_fee = DVN_FEE + DVN_FEE_2 + EXECUTOR_FEE + TREASURY_FEE;
330
+ assert(
331
+ total_native_fee_from_receipt(@message_receipt) == expected_total_fee,
332
+ 'incorrect total fee',
333
+ );
334
+ assert(
335
+ message_receipt.payees.len() == 4, 'incorrect payees count',
336
+ ); // 2 DVNs + 1 executor + 1 treasury = 4 total
337
+
338
+ // Verify DVN fees were paid (they should be in the DvnFeesPaid event)
339
+ let expected_dvn_payees = if dvn1_address < dvn2_address {
340
+ array![
341
+ Payee { receiver: dvn1_address, native_amount: DVN_FEE, lz_token_amount: 0 },
342
+ Payee { receiver: dvn2_address, native_amount: DVN_FEE_2, lz_token_amount: 0 },
343
+ ]
344
+ } else {
345
+ array![
346
+ Payee { receiver: dvn2_address, native_amount: DVN_FEE_2, lz_token_amount: 0 },
347
+ Payee { receiver: dvn1_address, native_amount: DVN_FEE, lz_token_amount: 0 },
348
+ ]
349
+ };
350
+
351
+ let packet_header = create_packet_header_from_packet(@packet);
352
+ spy
353
+ .assert_emitted(
354
+ @array![
355
+ (
356
+ contract_address,
357
+ UltraLightNode::Event::DvnFeesPaid(
358
+ DvnFeesPaid {
359
+ oapp: SENDER, payees: expected_dvn_payees, packet_header: packet_header,
360
+ },
361
+ ),
362
+ ),
363
+ ],
364
+ );
365
+ }
366
+
367
+ #[test]
368
+ fn test_send_with_optional_dvns() {
369
+ let (message_lib, _, admin, contract_address, _) = deploy_ultra_light_node(TREASURY_FEE);
370
+ let required_dvn = deploy_mock_dvn(DVN_FEE);
371
+ let optional_dvn1 = deploy_mock_dvn(DVN_FEE_OPTIONAL_1);
372
+ let optional_dvn2 = deploy_mock_dvn(DVN_FEE_OPTIONAL_2);
373
+ let executor_address = deploy_mock_executor(EXECUTOR_FEE);
374
+
375
+ // Setup default config with 1 required DVN and 2 optional DVNs with threshold 2
376
+ setup_default_config_with_mocks(
377
+ admin,
378
+ contract_address,
379
+ DST_EID,
380
+ array![required_dvn],
381
+ sort_contract_addresses(array![optional_dvn1, optional_dvn2]),
382
+ 2,
383
+ executor_address,
384
+ );
385
+
386
+ let packet = create_test_packet();
387
+ let options = create_empty_options();
388
+
389
+ // Call send as endpoint
390
+ start_cheat_caller_address(contract_address, ENDPOINT);
391
+ let MessageLibSendResult {
392
+ message_receipt, ..,
393
+ } = message_lib.send(packet.clone(), options, false);
394
+ stop_cheat_caller_address(contract_address);
395
+
396
+ // Verify receipt - should include all DVNs (required + optional)
397
+ let expected_total_fee = DVN_FEE
398
+ + DVN_FEE_OPTIONAL_1
399
+ + DVN_FEE_OPTIONAL_2
400
+ + EXECUTOR_FEE
401
+ + TREASURY_FEE;
402
+ assert(
403
+ total_native_fee_from_receipt(@message_receipt) == expected_total_fee,
404
+ 'incorrect total fee',
405
+ );
406
+ }
407
+
408
+ #[test]
409
+ fn test_send_with_zero_fees() {
410
+ let (message_lib, _, admin, contract_address, _) = deploy_ultra_light_node(ZERO_FEE);
411
+ let dvn_address = deploy_mock_dvn(ZERO_FEE);
412
+ let executor_address = deploy_mock_executor(ZERO_FEE);
413
+
414
+ // Setup default config
415
+ setup_default_config_with_mocks(
416
+ admin, contract_address, DST_EID, array![dvn_address], array![], 0, executor_address,
417
+ );
418
+
419
+ let packet = create_test_packet();
420
+ let options = create_empty_options();
421
+
422
+ // Call send as endpoint
423
+ start_cheat_caller_address(contract_address, ENDPOINT);
424
+ let MessageLibSendResult {
425
+ message_receipt, ..,
426
+ } = message_lib.send(packet.clone(), options, false);
427
+ stop_cheat_caller_address(contract_address);
428
+
429
+ // Verify receipt
430
+ assert(total_native_fee_from_receipt(@message_receipt) == ZERO_FEE, 'fee should be zero');
431
+ assert(message_receipt.payees.len() == 3, 'incorrect payees count');
432
+
433
+ // Verify all payees have zero amounts
434
+ for i in 0..message_receipt.payees.len() {
435
+ let payee = message_receipt.payees.at(i);
436
+ assert(*payee.native_amount == ZERO_FEE, 'payee amount should be zero');
437
+ }
438
+ }
439
+
440
+ #[test]
441
+ fn test_send_with_type3_options() {
442
+ let (message_lib, _, admin, contract_address, _) = deploy_ultra_light_node(TREASURY_FEE);
443
+ let dvn_address = deploy_mock_dvn(DVN_FEE);
444
+ let executor_address = deploy_mock_executor(EXECUTOR_FEE);
445
+
446
+ // Setup default config
447
+ setup_default_config_with_mocks(
448
+ admin, contract_address, DST_EID, array![dvn_address], array![], 0, executor_address,
449
+ );
450
+
451
+ let packet = create_test_packet();
452
+
453
+ // Create type 3 options with executor and DVN options
454
+ let mut options = Default::default();
455
+ options.append_u16(TYPE_3);
456
+ // Add executor option (worker_id=1, size=5, gas=100000)
457
+ options.append_u8(EXECUTOR_WORKER_ID);
458
+ options.append_u16(5); // option_size
459
+ options.append_u8(1); // option_type (LZ_RECEIVE)
460
+ options.append_u32(100000); // gas
461
+ // Add DVN option (worker_id=2, size=3, idx=0, type=1, data=0x01)
462
+ options.append_u8(DVN_WORKER_ID);
463
+ options.append_u16(3); // option_size
464
+ options.append_u8(0); // dvn_idx
465
+ options.append_u8(1); // option_type
466
+ options.append_u8(0x01); // option_data
467
+
468
+ // Call send as endpoint
469
+ start_cheat_caller_address(contract_address, ENDPOINT);
470
+ let MessageLibSendResult {
471
+ message_receipt, ..,
472
+ } = message_lib.send(packet.clone(), options, false);
473
+ stop_cheat_caller_address(contract_address);
474
+
475
+ // Should work with type 3 options
476
+ let expected_total_fee = DVN_FEE + EXECUTOR_FEE + TREASURY_FEE;
477
+ assert(
478
+ total_native_fee_from_receipt(@message_receipt) == expected_total_fee,
479
+ 'incorrect fee w/ type3 options',
480
+ );
481
+ }
482
+
483
+ #[test]
484
+ fn test_send_with_custom_oapp_config() {
485
+ let (message_lib, _, admin, contract_address, _) = deploy_ultra_light_node(TREASURY_FEE);
486
+ let default_dvn = deploy_mock_dvn(DVN_FEE);
487
+ let custom_dvn = deploy_mock_dvn(DVN_FEE_2);
488
+ let executor_address = deploy_mock_executor(EXECUTOR_FEE);
489
+
490
+ // Setup default config
491
+ setup_default_config_with_mocks(
492
+ admin, contract_address, DST_EID, array![default_dvn], array![], 0, executor_address,
493
+ );
494
+
495
+ // Set custom OApp config
496
+ let custom_config = create_test_uln_config(array![custom_dvn], array![], 0);
497
+ start_cheat_caller_address(contract_address, ENDPOINT);
498
+ set_oapp_uln_send_config_via_message_lib(contract_address, SENDER, DST_EID, custom_config);
499
+ stop_cheat_caller_address(contract_address);
500
+
501
+ let packet = create_test_packet();
502
+ let options = create_empty_options();
503
+
504
+ // Call send as endpoint
505
+ start_cheat_caller_address(contract_address, ENDPOINT);
506
+ let MessageLibSendResult {
507
+ message_receipt, ..,
508
+ } = message_lib.send(packet.clone(), options, false);
509
+ stop_cheat_caller_address(contract_address);
510
+
511
+ // Should use custom DVN fee, not default
512
+ let expected_total_fee = DVN_FEE_2 + EXECUTOR_FEE + TREASURY_FEE;
513
+ assert(
514
+ total_native_fee_from_receipt(@message_receipt) == expected_total_fee,
515
+ 'should use custom config',
516
+ );
517
+ }
518
+
519
+ #[test]
520
+ fn test_send_with_custom_executor_config() {
521
+ let (message_lib, _, admin, contract_address, _) = deploy_ultra_light_node(TREASURY_FEE);
522
+ let dvn_address = deploy_mock_dvn(DVN_FEE);
523
+ let default_executor = deploy_mock_executor(EXECUTOR_FEE);
524
+ let custom_executor = deploy_mock_executor(DVN_FEE_2); // Using different fee
525
+
526
+ // Setup default config
527
+ setup_default_config_with_mocks(
528
+ admin, contract_address, DST_EID, array![dvn_address], array![], 0, default_executor,
529
+ );
530
+
531
+ // Set custom executor config
532
+ let custom_executor_config = ExecutorConfig {
533
+ max_message_size: 2000, executor: custom_executor,
534
+ };
535
+ start_cheat_caller_address(contract_address, ENDPOINT);
536
+ set_oapp_executor_send_config_via_message_lib(
537
+ contract_address, SENDER, DST_EID, custom_executor_config,
538
+ );
539
+ stop_cheat_caller_address(contract_address);
540
+
541
+ let packet = create_test_packet();
542
+ let options = create_empty_options();
543
+
544
+ // Call send as endpoint
545
+ start_cheat_caller_address(contract_address, ENDPOINT);
546
+ let MessageLibSendResult {
547
+ message_receipt, ..,
548
+ } = message_lib.send(packet.clone(), options, false);
549
+ stop_cheat_caller_address(contract_address);
550
+
551
+ // Should use custom executor fee, not default
552
+ let expected_total_fee = DVN_FEE + DVN_FEE_2 + TREASURY_FEE;
553
+ assert(
554
+ total_native_fee_from_receipt(@message_receipt) == expected_total_fee,
555
+ 'should use custom executor',
556
+ );
557
+ }
558
+
559
+ #[test]
560
+ fn test_send_with_large_message() {
561
+ let (message_lib, _, admin, contract_address, _) = deploy_ultra_light_node(TREASURY_FEE);
562
+ let dvn_address = deploy_mock_dvn(DVN_FEE);
563
+ let executor_address = deploy_mock_executor(EXECUTOR_FEE);
564
+
565
+ // Setup default config with large max message size
566
+ start_cheat_caller_address(contract_address, OWNER);
567
+ let default_config = create_test_uln_config(array![dvn_address], array![], 0);
568
+ let config_params = array![SetDefaultUlnConfigParam { eid: DST_EID, config: default_config }];
569
+ admin.set_default_uln_send_config(config_params);
570
+
571
+ let executor_config = ExecutorConfig { max_message_size: 10000, executor: executor_address };
572
+ admin.set_default_executor_config(DST_EID, executor_config);
573
+ stop_cheat_caller_address(contract_address);
574
+
575
+ let mut large_packet = create_test_packet();
576
+ large_packet
577
+ .message =
578
+ "This is a much longer message that should still work because we set a large max_message_size in the executor config";
579
+
580
+ let options = create_empty_options();
581
+
582
+ // Call send as endpoint
583
+ start_cheat_caller_address(contract_address, ENDPOINT);
584
+ let MessageLibSendResult {
585
+ message_receipt, ..,
586
+ } = message_lib.send(large_packet.clone(), options, false);
587
+ stop_cheat_caller_address(contract_address);
588
+
589
+ // Should work with large message
590
+ let expected_total_fee = DVN_FEE + EXECUTOR_FEE + TREASURY_FEE;
591
+ assert(
592
+ total_native_fee_from_receipt(@message_receipt) == expected_total_fee,
593
+ 'incorrect fee w/ large message',
594
+ );
595
+ }
596
+
597
+ // Error test cases
598
+ #[test]
599
+ #[feature("safe_dispatcher")]
600
+ fn test_send_fails_when_not_called_by_endpoint() {
601
+ let (_, message_lib_safe, admin, contract_address, _) = deploy_ultra_light_node(TREASURY_FEE);
602
+ let dvn_address = deploy_mock_dvn(DVN_FEE);
603
+ let executor_address = deploy_mock_executor(EXECUTOR_FEE);
604
+
605
+ // Setup default config
606
+ setup_default_config_with_mocks(
607
+ admin, contract_address, DST_EID, array![dvn_address], array![], 0, executor_address,
608
+ );
609
+
610
+ let packet = create_test_packet();
611
+ let options = create_empty_options();
612
+
613
+ // Call send as non-endpoint (should fail)
614
+ start_cheat_caller_address(contract_address, NON_ENDPOINT);
615
+ let result = message_lib_safe.send(packet, options, false);
616
+ assert_panic_with_error(result, err_caller_not_endpoint(NON_ENDPOINT, ENDPOINT));
617
+ }
618
+
619
+ #[test]
620
+ #[feature("safe_dispatcher")]
621
+ fn test_send_fails_with_unsupported_eid() {
622
+ let (_, message_lib_safe, _, contract_address, _) = deploy_ultra_light_node(TREASURY_FEE);
623
+
624
+ // Don't set up any default config, so EID is unsupported
625
+ let packet = create_test_packet();
626
+ let options = create_empty_options();
627
+
628
+ // Call send as endpoint (should fail)
629
+ start_cheat_caller_address(contract_address, ENDPOINT);
630
+ let result = message_lib_safe.send(packet, options, false);
631
+ stop_cheat_caller_address(contract_address);
632
+
633
+ // Should fail because no default config means no DVNs
634
+ assert_panic_with_error(result, err_must_have_at_least_one_dvn());
635
+ }
636
+
637
+ #[test]
638
+ #[feature("safe_dispatcher")]
639
+ fn test_send_fails_with_message_too_large() {
640
+ let (_, message_lib_safe, admin, contract_address, _) = deploy_ultra_light_node(TREASURY_FEE);
641
+ let dvn_address = deploy_mock_dvn(DVN_FEE);
642
+ let executor_address = deploy_mock_executor(EXECUTOR_FEE);
643
+
644
+ // Setup default config with small max message size
645
+ let small_max_size = 10_u32;
646
+ start_cheat_caller_address(contract_address, OWNER);
647
+ let default_config = create_test_uln_config(array![dvn_address], array![], 0);
648
+ let config_params = array![SetDefaultUlnConfigParam { eid: DST_EID, config: default_config }];
649
+ admin.set_default_uln_send_config(config_params);
650
+
651
+ let executor_config = ExecutorConfig {
652
+ max_message_size: small_max_size, executor: executor_address,
653
+ };
654
+ admin.set_default_executor_config(DST_EID, executor_config);
655
+ stop_cheat_caller_address(contract_address);
656
+
657
+ // Create packet with message larger than max_message_size
658
+ let mut large_packet = create_test_packet();
659
+ large_packet
660
+ .message =
661
+ "This message is definitely longer than 10 characters and should trigger the message too large error";
662
+
663
+ let options = create_empty_options();
664
+
665
+ // Call send as endpoint (should fail)
666
+ start_cheat_caller_address(contract_address, ENDPOINT);
667
+ let result = message_lib_safe.send(large_packet.clone(), options, false);
668
+ stop_cheat_caller_address(contract_address);
669
+
670
+ // Should fail with message too large error
671
+ let expected_error = err_message_too_large(large_packet.message.len(), small_max_size.into());
672
+ assert_panic_with_error(result, expected_error);
673
+ }
674
+
675
+ #[test]
676
+ fn test_send_events_emitted_correctly() {
677
+ let (message_lib, _, admin, contract_address, treasury) = deploy_ultra_light_node(TREASURY_FEE);
678
+ let dvn_address = deploy_mock_dvn(DVN_FEE);
679
+ let executor_address = deploy_mock_executor(EXECUTOR_FEE);
680
+
681
+ // Setup default config
682
+ setup_default_config_with_mocks(
683
+ admin, contract_address, DST_EID, array![dvn_address], array![], 0, executor_address,
684
+ );
685
+
686
+ let packet = create_test_packet();
687
+ let options = create_empty_options();
688
+
689
+ // Set up event spy
690
+ let mut spy = spy_events();
691
+
692
+ // Call send as endpoint
693
+ start_cheat_caller_address(contract_address, ENDPOINT);
694
+ message_lib.send(packet.clone(), options, false);
695
+ stop_cheat_caller_address(contract_address);
696
+
697
+ // Verify all three events were emitted in correct order
698
+ let packet_header = create_packet_header_from_packet(@packet);
699
+ spy
700
+ .assert_emitted(
701
+ @array![
702
+ (
703
+ contract_address,
704
+ UltraLightNode::Event::DvnFeesPaid(
705
+ DvnFeesPaid {
706
+ oapp: SENDER,
707
+ payees: array![
708
+ Payee {
709
+ receiver: dvn_address,
710
+ native_amount: DVN_FEE,
711
+ lz_token_amount: 0,
712
+ },
713
+ ],
714
+ packet_header: packet_header.clone(),
715
+ },
716
+ ),
717
+ ),
718
+ (
719
+ contract_address,
720
+ UltraLightNode::Event::ExecutorFeePaid(
721
+ ExecutorFeePaid {
722
+ oapp: SENDER,
723
+ payee: Payee {
724
+ receiver: executor_address,
725
+ native_amount: EXECUTOR_FEE,
726
+ lz_token_amount: 0,
727
+ },
728
+ packet_header: packet_header.clone(),
729
+ },
730
+ ),
731
+ ),
732
+ (
733
+ contract_address,
734
+ UltraLightNode::Event::TreasuryFeePaid(
735
+ TreasuryFeePaid {
736
+ oapp: SENDER,
737
+ payee: Payee {
738
+ receiver: treasury, native_amount: TREASURY_FEE, lz_token_amount: 0,
739
+ },
740
+ packet_header: packet_header.clone(),
741
+ },
742
+ ),
743
+ ),
744
+ ],
745
+ );
746
+ }
747
+
748
+ #[test]
749
+ #[feature("safe_dispatcher")]
750
+ fn test_send_with_mock_dvn_failure() {
751
+ let (_, message_lib_safe, admin, contract_address, _) = deploy_ultra_light_node(TREASURY_FEE);
752
+ let dvn_address = deploy_mock_dvn(DVN_FEE);
753
+ let executor_address = deploy_mock_executor(EXECUTOR_FEE);
754
+
755
+ // Setup default config
756
+ setup_default_config_with_mocks(
757
+ admin, contract_address, DST_EID, array![dvn_address], array![], 0, executor_address,
758
+ );
759
+
760
+ // Make DVN fail
761
+ let dvn_helpers = IMockDVNHelpersDispatcher { contract_address: dvn_address };
762
+ dvn_helpers.set_should_fail(true);
763
+
764
+ let packet = create_test_packet();
765
+ let options = create_empty_options();
766
+
767
+ // Call send as endpoint (should fail)
768
+ start_cheat_caller_address(contract_address, ENDPOINT);
769
+ let result = message_lib_safe.send(packet, options, false);
770
+ stop_cheat_caller_address(contract_address);
771
+
772
+ // Should fail because DVN is configured to fail
773
+ assert(result.is_err(), 'send should fail when DVN fails');
774
+ }
775
+
776
+ #[test]
777
+ #[feature("safe_dispatcher")]
778
+ fn test_send_with_mock_executor_failure() {
779
+ let (_, message_lib_safe, admin, contract_address, _) = deploy_ultra_light_node(TREASURY_FEE);
780
+ let dvn_address = deploy_mock_dvn(DVN_FEE);
781
+ let executor_address = deploy_mock_executor(EXECUTOR_FEE);
782
+
783
+ // Setup default config
784
+ setup_default_config_with_mocks(
785
+ admin, contract_address, DST_EID, array![dvn_address], array![], 0, executor_address,
786
+ );
787
+
788
+ // Make executor fail
789
+ let executor_helpers = IMockExecutorHelpersDispatcher { contract_address: executor_address };
790
+ executor_helpers.set_should_fail(true);
791
+
792
+ let packet = create_test_packet();
793
+ let options = create_empty_options();
794
+
795
+ // Call send as endpoint (should fail)
796
+ start_cheat_caller_address(contract_address, ENDPOINT);
797
+ let result = message_lib_safe.send(packet, options, false);
798
+ stop_cheat_caller_address(contract_address);
799
+
800
+ // Should fail because executor is configured to fail
801
+ assert(result.is_err(), 'executor fail -> send fail');
802
+ }
803
+
804
+ #[test]
805
+ fn test_send_returns_correct_encoded_packet() {
806
+ let (message_lib, _, admin, contract_address, _) = deploy_ultra_light_node(TREASURY_FEE);
807
+ let dvn_address = deploy_mock_dvn(DVN_FEE);
808
+ let executor_address = deploy_mock_executor(EXECUTOR_FEE);
809
+
810
+ // Setup default config
811
+ setup_default_config_with_mocks(
812
+ admin, contract_address, DST_EID, array![dvn_address], array![], 0, executor_address,
813
+ );
814
+
815
+ let packet = create_test_packet();
816
+ let options = create_empty_options();
817
+
818
+ // Call send as endpoint
819
+ start_cheat_caller_address(contract_address, ENDPOINT);
820
+ let MessageLibSendResult {
821
+ encoded_packet, ..,
822
+ } = message_lib.send(packet.clone(), options, false);
823
+ stop_cheat_caller_address(contract_address);
824
+
825
+ // Verify encoded packet is not empty and contains expected data
826
+ assert(encoded_packet.len() > 0, 'encoded packet is empty');
827
+
828
+ // Now we can actually decode and verify the packet contents
829
+ let decoded_packet = PacketV1Codec::decode(@encoded_packet);
830
+
831
+ // Verify all fields match the original packet
832
+ assert(decoded_packet.nonce == packet.nonce, 'nonce mismatch');
833
+ assert(decoded_packet.src_eid == packet.src_eid, 'src_eid mismatch');
834
+ assert(decoded_packet.sender == packet.sender, 'sender mismatch');
835
+ assert(decoded_packet.dst_eid == packet.dst_eid, 'dst_eid mismatch');
836
+ assert(decoded_packet.receiver == packet.receiver, 'receiver mismatch');
837
+ assert(decoded_packet.guid == packet.guid, 'guid mismatch');
838
+ assert(decoded_packet.message == packet.message, 'message mismatch');
839
+ }
840
+
841
+ #[test]
842
+ fn test_send_with_different_senders() {
843
+ let (message_lib, _, admin, contract_address, _) = deploy_ultra_light_node(TREASURY_FEE);
844
+ let dvn_address = deploy_mock_dvn(DVN_FEE);
845
+ let executor_address = deploy_mock_executor(EXECUTOR_FEE);
846
+
847
+ // Setup default config
848
+ setup_default_config_with_mocks(
849
+ admin, contract_address, DST_EID, array![dvn_address], array![], 0, executor_address,
850
+ );
851
+
852
+ let sender1: ContractAddress = 'sender1'.try_into().unwrap();
853
+ let sender2: ContractAddress = 'sender2'.try_into().unwrap();
854
+
855
+ let mut packet1 = create_test_packet();
856
+ packet1.sender = sender1;
857
+
858
+ let mut packet2 = create_test_packet();
859
+ packet2.sender = sender2;
860
+
861
+ let options = create_empty_options();
862
+
863
+ // Set up event spy
864
+ let mut spy = spy_events();
865
+
866
+ // Call send as endpoint for both packets
867
+ start_cheat_caller_address(contract_address, ENDPOINT);
868
+ let MessageLibSendResult {
869
+ message_receipt, ..,
870
+ } = message_lib.send(packet1.clone(), options.clone(), false);
871
+ let MessageLibSendResult {
872
+ message_receipt: receipt2, ..,
873
+ } = message_lib.send(packet2.clone(), options, false);
874
+ stop_cheat_caller_address(contract_address);
875
+
876
+ // Both should work and have the same fees
877
+ assert(
878
+ total_native_fee_from_receipt(@message_receipt) == total_native_fee_from_receipt(@receipt2),
879
+ 'fees should be equal',
880
+ );
881
+
882
+ // Verify events were emitted for both senders
883
+ let packet_header1 = create_packet_header_from_packet(@packet1);
884
+ let packet_header2 = create_packet_header_from_packet(@packet2);
885
+ spy
886
+ .assert_emitted(
887
+ @array![
888
+ (
889
+ contract_address,
890
+ UltraLightNode::Event::DvnFeesPaid(
891
+ DvnFeesPaid {
892
+ oapp: sender1,
893
+ payees: array![
894
+ Payee {
895
+ receiver: dvn_address,
896
+ native_amount: DVN_FEE,
897
+ lz_token_amount: 0,
898
+ },
899
+ ],
900
+ packet_header: packet_header1,
901
+ },
902
+ ),
903
+ ),
904
+ (
905
+ contract_address,
906
+ UltraLightNode::Event::DvnFeesPaid(
907
+ DvnFeesPaid {
908
+ oapp: sender2,
909
+ payees: array![
910
+ Payee {
911
+ receiver: dvn_address,
912
+ native_amount: DVN_FEE,
913
+ lz_token_amount: 0,
914
+ },
915
+ ],
916
+ packet_header: packet_header2,
917
+ },
918
+ ),
919
+ ),
920
+ ],
921
+ );
922
+ }
923
+
924
+ #[test]
925
+ fn test_send_native_cap_with_small_fees() {
926
+ // Use small DVN/executor fees so cap actually applies
927
+ let (message_lib, _, admin, contract_address, treasury) = deploy_ultra_light_node(
928
+ TREASURY_FEE_ABOVE_CAP,
929
+ );
930
+ let dvn_address = deploy_mock_dvn(10); // Small DVN fee
931
+ let executor_address = deploy_mock_executor(20); // Small executor fee
932
+
933
+ setup_default_config_with_mocks(
934
+ admin, contract_address, DST_EID, array![dvn_address], array![], 0, executor_address,
935
+ );
936
+
937
+ let packet = create_test_packet();
938
+ let options = create_empty_options();
939
+
940
+ start_cheat_caller_address(contract_address, ENDPOINT);
941
+ let MessageLibSendResult {
942
+ message_receipt, ..,
943
+ } = message_lib.send(packet.clone(), options, false);
944
+ stop_cheat_caller_address(contract_address);
945
+
946
+ // DVN=10, executor=20, total_other_fees=30, cap=200, treasury_quote=500
947
+ // max_native_fee = max(30, 200) = 200
948
+ // actual_treasury_fee = min(500, 200) = 200 (capped!)
949
+ let expected_total_fee = 10 + 20 + 200; // 230
950
+ assert(
951
+ total_native_fee_from_receipt(@message_receipt) == expected_total_fee,
952
+ 'treasury fee capped',
953
+ );
954
+
955
+ // Verify treasury payee has capped amount
956
+ let treasury_payee = message_receipt.payees.at(2); // Treasury is third payee
957
+ assert(*treasury_payee.receiver == treasury, 'wrong treasury receiver');
958
+ assert(*treasury_payee.native_amount == 200, 'treasury amount capped');
959
+ }
960
+
961
+ #[test]
962
+ fn test_send_native_cap_normal_operation() {
963
+ // Normal operation where treasury fee is below cap
964
+ let (message_lib, _, admin, contract_address, treasury) = deploy_ultra_light_node(TREASURY_FEE);
965
+ let dvn_address = deploy_mock_dvn(DVN_FEE);
966
+ let executor_address = deploy_mock_executor(EXECUTOR_FEE);
967
+
968
+ setup_default_config_with_mocks(
969
+ admin, contract_address, DST_EID, array![dvn_address], array![], 0, executor_address,
970
+ );
971
+
972
+ let packet = create_test_packet();
973
+ let options = create_empty_options();
974
+
975
+ start_cheat_caller_address(contract_address, ENDPOINT);
976
+ let MessageLibSendResult {
977
+ message_receipt, ..,
978
+ } = message_lib.send(packet.clone(), options, false);
979
+ stop_cheat_caller_address(contract_address);
980
+
981
+ // DVN=1000, executor=2000, total_other_fees=3000, cap=200, treasury_quote=50
982
+ // max_native_fee = max(3000, 200) = 3000
983
+ // actual_treasury_fee = min(50, 3000) = 50 (not capped)
984
+ let expected_total_fee = DVN_FEE + EXECUTOR_FEE + TREASURY_FEE; // 1000 + 2000 + 50 = 3050
985
+ assert(
986
+ total_native_fee_from_receipt(@message_receipt) == expected_total_fee,
987
+ 'normal treasury fee op',
988
+ );
989
+
990
+ // Verify treasury payee has correct amount
991
+ let treasury_payee = message_receipt.payees.at(2);
992
+ assert(*treasury_payee.receiver == treasury, 'wrong treasury receiver');
993
+ assert(*treasury_payee.native_amount == TREASURY_FEE, 'wrong treasury amount');
994
+ }
995
+
996
+ #[test]
997
+ fn test_send_native_cap_at_threshold() {
998
+ let (message_lib, _, admin, contract_address, treasury) = deploy_ultra_light_node(
999
+ TREASURY_FEE_AT_CAP,
1000
+ );
1001
+ let dvn_address = deploy_mock_dvn(100); // DVN fee
1002
+ let executor_address = deploy_mock_executor(100); // Executor fee
1003
+
1004
+ setup_default_config_with_mocks(
1005
+ admin, contract_address, DST_EID, array![dvn_address], array![], 0, executor_address,
1006
+ );
1007
+
1008
+ let packet = create_test_packet();
1009
+ let options = create_empty_options();
1010
+
1011
+ start_cheat_caller_address(contract_address, ENDPOINT);
1012
+ let MessageLibSendResult {
1013
+ message_receipt, ..,
1014
+ } = message_lib.send(packet.clone(), options, false);
1015
+ stop_cheat_caller_address(contract_address);
1016
+
1017
+ // DVN=100, executor=100, total_other_fees=200, cap=200, treasury_quote=200
1018
+ // max_native_fee = max(200, 200) = 200
1019
+ // actual_treasury_fee = min(200, 200) = 200
1020
+ let expected_total_fee = 100 + 100 + 200; // 400
1021
+ assert(
1022
+ total_native_fee_from_receipt(@message_receipt) == expected_total_fee,
1023
+ 'treasury fee at cap',
1024
+ );
1025
+
1026
+ // Verify treasury payee has correct amount
1027
+ let treasury_payee = message_receipt.payees.at(2);
1028
+ assert(*treasury_payee.receiver == treasury, 'wrong treasury receiver');
1029
+ assert(*treasury_payee.native_amount == TREASURY_FEE_AT_CAP, 'wrong treasury at cap');
1030
+ }
1031
+
1032
+ #[test]
1033
+ fn test_send_native_cap_above_threshold() {
1034
+ // Test scenario where total_other_fees significantly exceeds treasury_native_fee_cap
1035
+ // This tests the case where max_native_fee is driven by total_other_fees, not the cap
1036
+ let treasury_quote = 1000_u256; // Above cap but below total_other_fees
1037
+ let (message_lib, _, admin, contract_address, treasury) = deploy_ultra_light_node(
1038
+ treasury_quote,
1039
+ );
1040
+
1041
+ // Use high DVN and executor fees so total_other_fees >> cap
1042
+ let high_dvn_fee = 2000_u256;
1043
+ let high_executor_fee = 3000_u256;
1044
+ let dvn_address = deploy_mock_dvn(high_dvn_fee);
1045
+ let executor_address = deploy_mock_executor(high_executor_fee);
1046
+
1047
+ setup_default_config_with_mocks(
1048
+ admin, contract_address, DST_EID, array![dvn_address], array![], 0, executor_address,
1049
+ );
1050
+
1051
+ let packet = create_test_packet();
1052
+ let options = create_empty_options();
1053
+
1054
+ start_cheat_caller_address(contract_address, ENDPOINT);
1055
+ let MessageLibSendResult {
1056
+ message_receipt, ..,
1057
+ } = message_lib.send(packet.clone(), options, false);
1058
+ stop_cheat_caller_address(contract_address);
1059
+
1060
+ // DVN=2000, executor=3000, total_other_fees=5000, cap=200, treasury_quote=1000
1061
+ // max_native_fee = max(5000, 200) = 5000 (driven by total_other_fees, well above cap)
1062
+ // actual_treasury_fee = min(1000, 5000) = 1000 (limited by quote, not by max_native_fee)
1063
+ let expected_total_fee = high_dvn_fee
1064
+ + high_executor_fee
1065
+ + treasury_quote; // 2000 + 3000 + 1000 = 6000
1066
+ assert(
1067
+ total_native_fee_from_receipt(@message_receipt) == expected_total_fee,
1068
+ 'treasury fee above threshold',
1069
+ );
1070
+
1071
+ // Verify treasury payee has the quote amount (not capped by max_native_fee)
1072
+ let treasury_payee = message_receipt.payees.at(2);
1073
+ assert(*treasury_payee.receiver == treasury, 'wrong treasury receiver');
1074
+ assert(*treasury_payee.native_amount == treasury_quote, 'wrong treasury above threshold');
1075
+ }
1076
+
1077
+ #[test]
1078
+ #[fuzzer(runs: 10)]
1079
+ fn test_send_treasury_fee_in_lz_tokens(
1080
+ native_treasury_fee: u64, lz_token_treasury_fee: u64, dvn_fee: u64, executor_fee: u64,
1081
+ ) {
1082
+ let dvn_fee = dvn_fee.into();
1083
+ let executor_fee = executor_fee.into();
1084
+ let native_treasury_fee = native_treasury_fee.into();
1085
+ let lz_token_treasury_fee = lz_token_treasury_fee.into();
1086
+
1087
+ let (message_lib, _, admin, contract_address, treasury) = deploy_ultra_light_node(
1088
+ native_treasury_fee,
1089
+ );
1090
+
1091
+ IMockTreasuryHelpersDispatcher { contract_address: treasury }
1092
+ .set_lz_token_fee(Some(lz_token_treasury_fee));
1093
+
1094
+ let dvn_address = deploy_mock_dvn(dvn_fee);
1095
+ let executor_address = deploy_mock_executor(executor_fee);
1096
+
1097
+ setup_default_config_with_mocks(
1098
+ admin, contract_address, DST_EID, array![dvn_address], array![], 0, executor_address,
1099
+ );
1100
+
1101
+ let packet = create_test_packet();
1102
+ let options = create_empty_options();
1103
+
1104
+ start_cheat_caller_address(contract_address, ENDPOINT);
1105
+ let MessageLibSendResult {
1106
+ message_receipt, ..,
1107
+ } = message_lib.send(packet.clone(), options, true);
1108
+ let payees = message_receipt.payees;
1109
+ let payee = {
1110
+ let mut iterator = payees.span().into_iter();
1111
+ iterator.find(|payee| payee.receiver == @@treasury).unwrap()
1112
+ };
1113
+
1114
+ assert(*payee.native_amount == 0, 'non-zero native fee');
1115
+ assert(*payee.lz_token_amount == lz_token_treasury_fee, 'unexpected LZ token fee');
1116
+ }
1117
+
1118
+ #[test]
1119
+ #[fuzzer(runs: 10)]
1120
+ fn test_send_uncapped_treasury_fee_in_lz_tokens(
1121
+ native_treasury_fee: u64, dvn_fee: u64, executor_fee: u64,
1122
+ ) {
1123
+ let native_treasury_fee = native_treasury_fee.into();
1124
+ let dvn_fee = dvn_fee.into();
1125
+ let executor_fee = executor_fee.into();
1126
+
1127
+ let (message_lib, _, admin, contract_address, treasury) = deploy_ultra_light_node(
1128
+ native_treasury_fee,
1129
+ );
1130
+
1131
+ IMockTreasuryHelpersDispatcher { contract_address: treasury }.set_lz_token_fee(Some(MAX_U256));
1132
+
1133
+ let dvn_address = deploy_mock_dvn(dvn_fee);
1134
+ let executor_address = deploy_mock_executor(executor_fee);
1135
+
1136
+ setup_default_config_with_mocks(
1137
+ admin, contract_address, DST_EID, array![dvn_address], array![], 0, executor_address,
1138
+ );
1139
+
1140
+ let packet = create_test_packet();
1141
+ let options = create_empty_options();
1142
+
1143
+ start_cheat_caller_address(contract_address, ENDPOINT);
1144
+ let MessageLibSendResult {
1145
+ message_receipt, ..,
1146
+ } = message_lib.send(packet.clone(), options, true);
1147
+ let payees = message_receipt.payees;
1148
+ let payee = {
1149
+ let mut iterator = payees.span().into_iter();
1150
+ iterator.find(|payee| payee.receiver == @@treasury).unwrap()
1151
+ };
1152
+
1153
+ assert(*payee.native_amount == 0, 'non-zero native fee');
1154
+ assert(*payee.lz_token_amount == MAX_U256, 'unexpected LZ token fee');
1155
+ }