@layerzerolabs/protocol-stellar-v2 0.2.8 → 0.2.10

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 (239) hide show
  1. package/.turbo/turbo-build.log +443 -302
  2. package/.turbo/turbo-lint.log +118 -96
  3. package/.turbo/turbo-test.log +853 -731
  4. package/Cargo.lock +120 -37
  5. package/Cargo.toml +8 -5
  6. package/contracts/common-macros/src/contract_impl.rs +44 -0
  7. package/contracts/common-macros/src/lib.rs +86 -40
  8. package/contracts/common-macros/src/ownable.rs +24 -32
  9. package/contracts/common-macros/src/storage.rs +95 -120
  10. package/contracts/common-macros/src/tests/contract_impl.rs +289 -0
  11. package/contracts/common-macros/src/tests/mod.rs +9 -0
  12. package/contracts/common-macros/src/tests/ownable.rs +151 -0
  13. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__contract_impl__snapshot_generated_contract_impl_code.snap +85 -0
  14. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_generated_ownable_code.snap +30 -0
  15. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_only_owner_preserves_function_signature.snap +9 -0
  16. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__storage__snapshot_generated_storage_code.snap +1072 -0
  17. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +45 -0
  18. package/contracts/common-macros/src/tests/storage.rs +485 -0
  19. package/contracts/common-macros/src/tests/test_helpers.rs +93 -0
  20. package/contracts/common-macros/src/tests/ttl_configurable.rs +34 -0
  21. package/contracts/common-macros/src/ttl_configurable.rs +31 -14
  22. package/contracts/common-macros/src/utils.rs +27 -0
  23. package/contracts/endpoint-v2/ARCHITECTURE.md +4 -4
  24. package/contracts/endpoint-v2/src/endpoint_v2.rs +18 -15
  25. package/contracts/endpoint-v2/src/interfaces/message_lib.rs +2 -3
  26. package/contracts/endpoint-v2/src/interfaces/message_lib_manager.rs +5 -3
  27. package/contracts/endpoint-v2/src/interfaces/messaging_channel.rs +2 -2
  28. package/contracts/endpoint-v2/src/interfaces/messaging_composer.rs +2 -2
  29. package/contracts/endpoint-v2/src/interfaces/send_lib.rs +4 -4
  30. package/contracts/endpoint-v2/src/lib.rs +6 -5
  31. package/contracts/endpoint-v2/src/message_lib_manager.rs +14 -6
  32. package/contracts/endpoint-v2/src/messaging_channel.rs +6 -2
  33. package/contracts/endpoint-v2/src/messaging_composer.rs +6 -2
  34. package/contracts/endpoint-v2/src/storage.rs +10 -7
  35. package/contracts/endpoint-v2/src/tests/endpoint_v2/pay_messaging_fees.rs +16 -16
  36. package/contracts/endpoint-v2/src/tests/endpoint_v2/ttl_config.rs +46 -46
  37. package/contracts/endpoint-v2/src/tests/mock.rs +2 -2
  38. package/contracts/endpoint-v2/src/util.rs +8 -2
  39. package/contracts/message-libs/block-message-lib/Cargo.toml +1 -0
  40. package/contracts/message-libs/block-message-lib/src/lib.rs +5 -5
  41. package/contracts/message-libs/message-lib-common/src/errors.rs +8 -8
  42. package/contracts/message-libs/message-lib-common/src/interfaces/dvn.rs +0 -1
  43. package/contracts/message-libs/message-lib-common/src/interfaces/mod.rs +3 -3
  44. package/contracts/message-libs/message-lib-common/src/lib.rs +0 -2
  45. package/contracts/message-libs/message-lib-common/src/packet_codec_v1.rs +4 -6
  46. package/contracts/message-libs/message-lib-common/src/tests/packet_codec_v1.rs +2 -2
  47. package/contracts/message-libs/message-lib-common/src/tests/worker_options.rs +11 -11
  48. package/contracts/message-libs/message-lib-common/src/worker_options.rs +10 -16
  49. package/contracts/message-libs/simple-message-lib/src/errors.rs +0 -4
  50. package/contracts/message-libs/simple-message-lib/src/simple_message_lib.rs +49 -34
  51. package/contracts/message-libs/simple-message-lib/src/storage.rs +3 -7
  52. package/contracts/message-libs/simple-message-lib/src/test.rs +3 -3
  53. package/contracts/message-libs/treasury/src/storage.rs +1 -2
  54. package/contracts/message-libs/treasury/src/tests/setup.rs +3 -2
  55. package/contracts/message-libs/treasury/src/tests/treasury_tests.rs +0 -13
  56. package/contracts/message-libs/treasury/src/treasury.rs +18 -21
  57. package/contracts/message-libs/uln-302/Cargo.toml +1 -0
  58. package/contracts/message-libs/uln-302/src/interfaces/mod.rs +4 -4
  59. package/contracts/message-libs/uln-302/src/interfaces/{receive.rs → receive_uln.rs} +3 -3
  60. package/contracts/message-libs/uln-302/src/interfaces/{send.rs → send_uln.rs} +8 -80
  61. package/contracts/message-libs/uln-302/src/lib.rs +5 -4
  62. package/contracts/message-libs/uln-302/src/{receive.rs → receive_uln.rs} +20 -12
  63. package/contracts/message-libs/uln-302/src/{send.rs → send_uln.rs} +19 -13
  64. package/contracts/message-libs/uln-302/src/storage.rs +1 -2
  65. package/contracts/message-libs/uln-302/src/tests/config/uln_config.rs +3 -2
  66. package/contracts/message-libs/uln-302/src/tests/send_uln302/send.rs +30 -30
  67. package/contracts/message-libs/uln-302/src/tests/setup.rs +12 -11
  68. package/contracts/message-libs/uln-302/src/tests/uln302/set_config.rs +1 -1
  69. package/contracts/message-libs/uln-302/src/{config_validation.rs → types.rs} +79 -11
  70. package/contracts/message-libs/uln-302/src/uln302.rs +15 -10
  71. package/contracts/oapp-macros/Cargo.toml +2 -8
  72. package/contracts/oapp-macros/src/lib.rs +57 -311
  73. package/contracts/oapp-macros/src/oapp_core.rs +23 -32
  74. package/contracts/oapp-macros/src/oapp_full.rs +8 -2
  75. package/contracts/oapp-macros/src/oapp_options_type3.rs +21 -36
  76. package/contracts/oapp-macros/src/oapp_receiver.rs +38 -57
  77. package/contracts/oapp-macros/src/oapp_sender.rs +12 -14
  78. package/contracts/oapp-macros/src/util.rs +14 -10
  79. package/contracts/oapps/counter/Cargo.toml +2 -1
  80. package/contracts/oapps/counter/integration_tests/utils.rs +4 -4
  81. package/contracts/oapps/counter/src/codec.rs +8 -9
  82. package/contracts/oapps/counter/src/counter.rs +156 -147
  83. package/contracts/oapps/counter/src/storage.rs +1 -2
  84. package/contracts/oapps/counter/src/tests/test_codec.rs +5 -5
  85. package/contracts/oapps/counter/src/tests/test_counter.rs +11 -13
  86. package/contracts/oapps/oapp/Cargo.toml +1 -0
  87. package/contracts/oapps/oapp/src/errors.rs +1 -1
  88. package/contracts/oapps/oapp/src/lib.rs +3 -0
  89. package/contracts/oapps/oapp/src/macro_tests/mod.rs +1 -0
  90. package/contracts/oapps/oapp/src/macro_tests/test_macros.rs +312 -0
  91. package/contracts/oapps/oapp/src/oapp_core.rs +52 -53
  92. package/contracts/oapps/oapp/src/oapp_options_type3.rs +18 -28
  93. package/contracts/oapps/oapp/src/oapp_receiver.rs +82 -31
  94. package/contracts/oapps/oapp/src/oapp_sender.rs +55 -13
  95. package/contracts/oapps/oapp/src/tests/test_oapp_core.rs +16 -3
  96. package/contracts/oapps/oapp/src/tests/test_oapp_options_type3.rs +33 -8
  97. package/contracts/oapps/oapp/src/tests/test_oapp_receiver.rs +6 -9
  98. package/contracts/oapps/oapp/src/tests/test_oapp_sender.rs +28 -15
  99. package/contracts/oapps/oft/Cargo.toml +27 -0
  100. package/contracts/oapps/oft/integration-tests/mod.rs +3 -0
  101. package/contracts/oapps/oft/integration-tests/setup.rs +320 -0
  102. package/contracts/oapps/oft/integration-tests/test_with_sml.rs +155 -0
  103. package/contracts/oapps/oft/integration-tests/utils.rs +201 -0
  104. package/contracts/oapps/oft/src/codec/mod.rs +2 -0
  105. package/contracts/oapps/oft/src/codec/oft_compose_msg_codec.rs +55 -0
  106. package/contracts/oapps/oft/src/codec/oft_msg_codec.rs +62 -0
  107. package/contracts/oapps/oft/src/constants.rs +5 -0
  108. package/contracts/oapps/oft/src/errors.rs +8 -0
  109. package/contracts/oapps/oft/src/events.rs +19 -0
  110. package/contracts/oapps/oft/src/interfaces/mint_burn_token.rs +23 -0
  111. package/contracts/oapps/oft/src/interfaces/mod.rs +3 -0
  112. package/contracts/oapps/oft/src/lib.rs +22 -0
  113. package/contracts/oapps/oft/src/macro_tests/mod.rs +2 -0
  114. package/contracts/oapps/oft/src/macro_tests/test_all_default.rs +41 -0
  115. package/contracts/oapps/oft/src/macro_tests/test_override.rs +83 -0
  116. package/contracts/oapps/oft/src/oft.rs +320 -0
  117. package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +50 -0
  118. package/contracts/oapps/oft/src/oft_types/mint_burn.rs +50 -0
  119. package/contracts/oapps/oft/src/oft_types/mod.rs +10 -0
  120. package/contracts/oapps/oft/src/storage.rs +11 -0
  121. package/contracts/oapps/oft/src/tests/mod.rs +13 -0
  122. package/contracts/oapps/oft/src/tests/test_decimals.rs +89 -0
  123. package/contracts/oapps/oft/src/tests/test_lz_receive.rs +282 -0
  124. package/contracts/oapps/oft/src/tests/test_oft_compose_msg_codec.rs +68 -0
  125. package/contracts/oapps/oft/src/tests/test_oft_msg_codec.rs +136 -0
  126. package/contracts/oapps/oft/src/tests/test_oft_version.rs +13 -0
  127. package/contracts/oapps/oft/src/tests/test_quote_oft.rs +159 -0
  128. package/contracts/oapps/oft/src/tests/test_quote_send.rs +195 -0
  129. package/contracts/oapps/oft/src/tests/test_resolve_address.rs +37 -0
  130. package/contracts/oapps/oft/src/tests/test_send.rs +915 -0
  131. package/contracts/oapps/oft/src/tests/test_token.rs +47 -0
  132. package/contracts/oapps/oft/src/tests/test_utils.rs +789 -0
  133. package/contracts/oapps/oft/src/types.rs +38 -0
  134. package/contracts/oapps/oft/src/utils.rs +67 -0
  135. package/contracts/oapps/oft-mint-burn/Cargo.toml +26 -0
  136. package/contracts/oapps/oft-mint-burn/src/lib.rs +3 -0
  137. package/contracts/oapps/oft-mint-burn/src/oft.rs +28 -0
  138. package/contracts/oapps/oft-mint-burn/src/tests/mod.rs +1 -0
  139. package/contracts/utils/src/buffer_reader.rs +8 -9
  140. package/contracts/utils/src/buffer_writer.rs +11 -5
  141. package/contracts/utils/src/errors.rs +5 -5
  142. package/contracts/utils/src/ownable.rs +14 -6
  143. package/contracts/utils/src/testing_utils.rs +11 -1
  144. package/contracts/utils/src/tests/buffer_reader.rs +491 -730
  145. package/contracts/utils/src/tests/buffer_writer.rs +336 -148
  146. package/contracts/utils/src/tests/bytes_ext.rs +125 -40
  147. package/contracts/utils/src/tests/mod.rs +3 -0
  148. package/contracts/utils/src/tests/ownable.rs +379 -27
  149. package/contracts/utils/src/tests/test_helper.rs +47 -0
  150. package/contracts/utils/src/tests/testing_utils.rs +555 -0
  151. package/contracts/utils/src/tests/ttl.rs +421 -0
  152. package/contracts/utils/src/ttl.rs +29 -89
  153. package/contracts/workers/dvn/Cargo.toml +31 -0
  154. package/contracts/workers/dvn/src/auth.rs +66 -0
  155. package/contracts/workers/dvn/src/dvn.rs +143 -0
  156. package/contracts/workers/dvn/src/errors.rs +21 -0
  157. package/contracts/workers/dvn/src/events.rs +19 -0
  158. package/contracts/workers/dvn/src/interfaces/dvn.rs +12 -0
  159. package/contracts/workers/dvn/src/interfaces/mod.rs +5 -0
  160. package/contracts/workers/dvn/src/interfaces/multisig.rs +15 -0
  161. package/contracts/workers/dvn/src/lib.rs +24 -0
  162. package/contracts/workers/dvn/src/multisig.rs +127 -0
  163. package/contracts/workers/dvn/src/storage.rs +35 -0
  164. package/contracts/workers/dvn/src/tests/auth.rs +237 -0
  165. package/contracts/workers/dvn/src/tests/dvn.rs +349 -0
  166. package/contracts/workers/dvn/src/tests/key_pair.rs +66 -0
  167. package/contracts/workers/dvn/src/tests/mod.rs +5 -0
  168. package/contracts/workers/dvn/src/tests/multisig/mod.rs +3 -0
  169. package/contracts/workers/dvn/src/tests/multisig/set_signer.rs +133 -0
  170. package/contracts/workers/dvn/src/tests/multisig/set_threshold.rs +108 -0
  171. package/contracts/workers/dvn/src/tests/multisig/verify_signatures.rs +109 -0
  172. package/contracts/workers/dvn/src/tests/setup.rs +109 -0
  173. package/contracts/workers/dvn/src/types.rs +26 -0
  174. package/contracts/workers/dvn-fee-lib/Cargo.toml +24 -0
  175. package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +113 -0
  176. package/contracts/workers/dvn-fee-lib/src/errors.rs +8 -0
  177. package/contracts/workers/dvn-fee-lib/src/lib.rs +17 -0
  178. package/contracts/workers/dvn-fee-lib/src/tests/dvn_fee_lib.rs +282 -0
  179. package/contracts/workers/dvn-fee-lib/src/tests/mod.rs +1 -0
  180. package/contracts/workers/executor/Cargo.toml +10 -7
  181. package/contracts/workers/executor/src/errors.rs +8 -0
  182. package/contracts/workers/executor/src/events.rs +4 -7
  183. package/contracts/workers/executor/src/interfaces/executor.rs +72 -22
  184. package/contracts/workers/executor/src/interfaces/mod.rs +0 -2
  185. package/contracts/workers/executor/src/lib.rs +16 -7
  186. package/contracts/workers/executor/src/lz_executor.rs +308 -0
  187. package/contracts/workers/executor/src/storage.rs +24 -16
  188. package/contracts/workers/executor-fee-lib/Cargo.toml +22 -0
  189. package/contracts/workers/executor-fee-lib/src/errors.rs +15 -0
  190. package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +215 -0
  191. package/contracts/workers/executor-fee-lib/src/executor_option.rs +203 -0
  192. package/contracts/workers/executor-fee-lib/src/lib.rs +7 -0
  193. package/contracts/workers/executor-helper/Cargo.toml +29 -0
  194. package/contracts/workers/executor-helper/src/executor_helper.rs +161 -0
  195. package/contracts/workers/executor-helper/src/lib.rs +11 -0
  196. package/contracts/workers/{worker-common → worker}/Cargo.toml +1 -4
  197. package/contracts/workers/worker/src/errors.rs +24 -0
  198. package/contracts/workers/worker/src/events.rs +62 -0
  199. package/contracts/workers/worker/src/interfaces/dvn_fee_lib.rs +75 -0
  200. package/contracts/workers/worker/src/interfaces/executor_fee_lib.rs +84 -0
  201. package/contracts/workers/{worker-common → worker}/src/interfaces/mod.rs +2 -2
  202. package/contracts/workers/worker/src/interfaces/price_feed.rs +85 -0
  203. package/contracts/workers/worker/src/lib.rs +14 -0
  204. package/contracts/workers/worker/src/storage.rs +63 -0
  205. package/contracts/workers/worker/src/worker.rs +459 -0
  206. package/package.json +3 -3
  207. package/sdk/dist/generated/bml.d.ts +88 -17
  208. package/sdk/dist/generated/bml.js +62 -16
  209. package/sdk/dist/generated/counter.d.ts +281 -102
  210. package/sdk/dist/generated/counter.js +93 -41
  211. package/sdk/dist/generated/endpoint.d.ts +128 -105
  212. package/sdk/dist/generated/endpoint.js +47 -45
  213. package/sdk/dist/generated/sml.d.ts +212 -69
  214. package/sdk/dist/generated/sml.js +103 -53
  215. package/sdk/dist/generated/uln302.d.ts +270 -173
  216. package/sdk/dist/generated/uln302.js +112 -64
  217. package/sdk/package.json +11 -11
  218. package/sdk/test/index.test.ts +147 -42
  219. package/sdk/test/suites/constants.ts +7 -3
  220. package/sdk/test/suites/deploy.ts +65 -42
  221. package/sdk/test/suites/localnet.ts +2 -2
  222. package/sdk/test/suites/scan.ts +28 -25
  223. package/sdk/test/utils.ts +199 -0
  224. package/sdk/tsconfig.json +93 -95
  225. package/tools/ts-bindings-gen/src/main.rs +2 -0
  226. package/contracts/common-macros/src/snapshots/common_macros__tests__tests__snapshot_generated_storage_code.snap +0 -310
  227. package/contracts/common-macros/src/tests.rs +0 -287
  228. package/contracts/oapp-macros/tests/test_macros.rs +0 -522
  229. package/contracts/workers/executor/src/executor.rs +0 -347
  230. package/contracts/workers/executor/src/interfaces/types.rs +0 -51
  231. package/contracts/workers/worker-common/src/constants.rs +0 -17
  232. package/contracts/workers/worker-common/src/errors.rs +0 -6
  233. package/contracts/workers/worker-common/src/events.rs +0 -34
  234. package/contracts/workers/worker-common/src/interfaces/executor_fee_lib.rs +0 -35
  235. package/contracts/workers/worker-common/src/interfaces/price_feed.rs +0 -40
  236. package/contracts/workers/worker-common/src/interfaces/worker.rs +0 -60
  237. package/contracts/workers/worker-common/src/lib.rs +0 -19
  238. package/contracts/workers/worker-common/src/storage.rs +0 -32
  239. package/contracts/workers/worker-common/src/worker_common.rs +0 -166
@@ -0,0 +1,915 @@
1
+ use crate::{
2
+ errors::OFTError,
3
+ events::OFTSent,
4
+ tests::test_utils::OFTTestSetupBuilder,
5
+ types::{OFTReceipt, SendParam},
6
+ };
7
+ use endpoint_v2::MessagingFee;
8
+ use oapp::errors::OAppError;
9
+ use soroban_sdk::{
10
+ bytes,
11
+ testutils::{Address as _, MockAuth, MockAuthInvoke},
12
+ Address, Bytes, BytesN, Env, IntoVal,
13
+ };
14
+ use utils::testing_utils::assert_event;
15
+
16
+ use super::test_utils::{create_send_param, OFTTestSetup};
17
+
18
+ // ==================== Basic Send Tests ====================
19
+
20
+ #[test]
21
+ fn test_send_basic() {
22
+ let env = Env::default();
23
+ let setup = OFTTestSetup::new(&env);
24
+
25
+ let sender = Address::generate(&env);
26
+
27
+ // Set peer
28
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
29
+ let dst_eid = 100u32;
30
+ setup.set_peer(dst_eid, &peer);
31
+
32
+ // SAC has 7 decimals, shared is 6, conversion rate = 10
33
+ // Use amount with no dust
34
+ let amount_ld = 12345670i128;
35
+
36
+ // Fund sender with tokens and native fees
37
+ setup.fund_tokens(&sender, amount_ld);
38
+ setup.fund_native_fees(&sender, setup.native_fee);
39
+ assert_eq!(setup.token_client.balance(&sender), amount_ld);
40
+
41
+ let send_param = create_send_param(&env, dst_eid, amount_ld, amount_ld);
42
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
43
+ let refund_address = sender.clone();
44
+ let oft_receipt = setup.quote_oft(&send_param);
45
+
46
+ // Send tokens
47
+ let (msg_receipt, oft_receipt) = setup.send(&sender, &send_param, &fee, &refund_address, &oft_receipt);
48
+
49
+ // Verify messaging receipt
50
+ assert!(msg_receipt.nonce > 0);
51
+ assert_eq!(msg_receipt.fee.native_fee, setup.native_fee);
52
+
53
+ // Verify OFT receipt
54
+ assert_eq!(oft_receipt.amount_sent_ld, amount_ld);
55
+ assert_eq!(oft_receipt.amount_received_ld, amount_ld);
56
+
57
+ // Verify tokens were burned (MintBurn OFT)
58
+ assert_eq!(setup.token_client.balance(&sender), 0);
59
+
60
+ // Verify endpoint was called
61
+ assert!(setup.endpoint_client.was_sent());
62
+ assert_eq!(setup.endpoint_client.get_last_dst_eid(), Some(dst_eid));
63
+ }
64
+
65
+ #[test]
66
+ fn test_send_burns_tokens() {
67
+ let env = Env::default();
68
+ let setup = OFTTestSetup::new(&env);
69
+
70
+ let sender = Address::generate(&env);
71
+
72
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
73
+ let dst_eid = 100u32;
74
+ setup.set_peer(dst_eid, &peer);
75
+
76
+ // Fund more tokens than we'll send
77
+ let initial_balance = 100_000_000i128;
78
+ let send_amount = 50_000_000i128;
79
+ setup.fund_tokens(&sender, initial_balance);
80
+ setup.fund_native_fees(&sender, setup.native_fee);
81
+
82
+ let send_param = create_send_param(&env, dst_eid, send_amount, send_amount);
83
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
84
+ let oft_receipt = setup.quote_oft(&send_param);
85
+
86
+ setup.send(&sender, &send_param, &fee, &sender, &oft_receipt);
87
+
88
+ // Verify only sent amount was burned
89
+ assert_eq!(setup.token_client.balance(&sender), initial_balance - send_amount);
90
+ }
91
+
92
+ #[test]
93
+ fn test_send_with_dust_removal() {
94
+ let env = Env::default();
95
+ let setup = OFTTestSetup::new(&env);
96
+
97
+ let sender = Address::generate(&env);
98
+
99
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
100
+ let dst_eid = 100u32;
101
+ setup.set_peer(dst_eid, &peer);
102
+
103
+ // SAC has 7 decimals, shared is 6, conversion rate = 10
104
+ // Amount with dust (last digit will be removed)
105
+ let amount_with_dust = 12345678i128;
106
+ let expected_dust_removed = 12345670i128;
107
+
108
+ setup.fund_tokens(&sender, amount_with_dust);
109
+ setup.fund_native_fees(&sender, setup.native_fee);
110
+
111
+ // min_amount_ld should be the dust-removed amount
112
+ let send_param = create_send_param(&env, dst_eid, amount_with_dust, expected_dust_removed);
113
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
114
+ let quoted_receipt = setup.quote_oft(&send_param);
115
+
116
+ let (_, oft_receipt) = setup.send(&sender, &send_param, &fee, &sender, &quoted_receipt);
117
+
118
+ // Verify dust was removed
119
+ assert_eq!(oft_receipt.amount_sent_ld, expected_dust_removed);
120
+ assert_eq!(oft_receipt.amount_received_ld, expected_dust_removed);
121
+
122
+ // Only dust-removed amount should be burned
123
+ assert_eq!(setup.token_client.balance(&sender), amount_with_dust - expected_dust_removed);
124
+ }
125
+
126
+ // ==================== Slippage Tests ====================
127
+
128
+ #[test]
129
+ fn test_send_slippage_exactly_met() {
130
+ let env = Env::default();
131
+ let setup = OFTTestSetup::new(&env);
132
+
133
+ let sender = Address::generate(&env);
134
+
135
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
136
+ let dst_eid = 100u32;
137
+ setup.set_peer(dst_eid, &peer);
138
+
139
+ let amount_ld = 12345670i128;
140
+ setup.fund_tokens(&sender, amount_ld);
141
+ setup.fund_native_fees(&sender, setup.native_fee);
142
+
143
+ // min_amount_ld exactly equals amount after dust removal
144
+ let send_param = create_send_param(&env, dst_eid, amount_ld, amount_ld);
145
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
146
+ let quoted_receipt = setup.quote_oft(&send_param);
147
+
148
+ let (_, oft_receipt) = setup.send(&sender, &send_param, &fee, &sender, &quoted_receipt);
149
+
150
+ assert_eq!(oft_receipt.amount_received_ld, amount_ld);
151
+ }
152
+
153
+ #[test]
154
+ fn test_send_slippage_exceeded() {
155
+ let env = Env::default();
156
+ let setup = OFTTestSetup::new(&env);
157
+
158
+ let sender = Address::generate(&env);
159
+
160
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
161
+ let dst_eid = 100u32;
162
+ setup.set_peer(dst_eid, &peer);
163
+
164
+ // Amount with dust that will be removed
165
+ let amount_with_dust = 12345678i128;
166
+ // min_amount_ld higher than what will be received after dust removal
167
+ let min_amount_too_high = 12345678i128; // Same as input, but dust will be removed
168
+
169
+ setup.fund_tokens(&sender, amount_with_dust);
170
+ setup.fund_native_fees(&sender, setup.native_fee);
171
+
172
+ let send_param = create_send_param(&env, dst_eid, amount_with_dust, min_amount_too_high);
173
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
174
+ // Use a receipt with dust-removed amount for auth (even though it will fail slippage check)
175
+ let quoted_receipt = setup.quote_oft(&create_send_param(&env, dst_eid, amount_with_dust, 0));
176
+
177
+ // Should fail due to slippage
178
+ let result = setup.try_send(&sender, &send_param, &fee, &sender, &quoted_receipt);
179
+ assert_eq!(result.err().unwrap().ok().unwrap(), OFTError::SlippageExceeded.into());
180
+ }
181
+
182
+ #[test]
183
+ fn test_send_slippage_less_than_received() {
184
+ let env = Env::default();
185
+ let setup = OFTTestSetup::new(&env);
186
+
187
+ let sender = Address::generate(&env);
188
+
189
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
190
+ let dst_eid = 100u32;
191
+ setup.set_peer(dst_eid, &peer);
192
+
193
+ let amount_ld = 12345670i128;
194
+ // min_amount_ld less than what will be received
195
+ let min_amount_low = 10000000i128;
196
+
197
+ setup.fund_tokens(&sender, amount_ld);
198
+ setup.fund_native_fees(&sender, setup.native_fee);
199
+
200
+ let send_param = create_send_param(&env, dst_eid, amount_ld, min_amount_low);
201
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
202
+ let quoted_receipt = setup.quote_oft(&send_param);
203
+
204
+ let (_, oft_receipt) = setup.send(&sender, &send_param, &fee, &sender, &quoted_receipt);
205
+
206
+ // Should succeed, receiving more than minimum
207
+ assert!(oft_receipt.amount_received_ld >= min_amount_low);
208
+ assert_eq!(oft_receipt.amount_received_ld, amount_ld);
209
+ }
210
+
211
+ // ==================== Error Cases ====================
212
+
213
+ #[test]
214
+ fn test_send_no_peer_set() {
215
+ let env = Env::default();
216
+ let setup = OFTTestSetup::new(&env);
217
+
218
+ let sender = Address::generate(&env);
219
+ let amount_ld = 12345670i128;
220
+ setup.fund_tokens(&sender, amount_ld);
221
+ setup.fund_native_fees(&sender, setup.native_fee);
222
+
223
+ // Don't set peer - should fail
224
+ let send_param = create_send_param(&env, 100, amount_ld, amount_ld);
225
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
226
+ // Create a dummy receipt for auth (will fail before burn anyway)
227
+ let dummy_receipt = OFTReceipt { amount_sent_ld: amount_ld, amount_received_ld: amount_ld };
228
+
229
+ let result = setup.try_send(&sender, &send_param, &fee, &sender, &dummy_receipt);
230
+ assert_eq!(result.err().unwrap().ok().unwrap(), OAppError::NoPeer.into());
231
+ }
232
+
233
+ #[test]
234
+ fn test_send_zero_amount() {
235
+ let env = Env::default();
236
+ let setup = OFTTestSetup::new(&env);
237
+
238
+ let sender = Address::generate(&env);
239
+
240
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
241
+ let dst_eid = 100u32;
242
+ setup.set_peer(dst_eid, &peer);
243
+
244
+ // Fund native fees for sending
245
+ setup.fund_native_fees(&sender, setup.native_fee);
246
+
247
+ // Send zero tokens
248
+ let send_param = create_send_param(&env, dst_eid, 0, 0);
249
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
250
+ let quoted_receipt = setup.quote_oft(&send_param);
251
+
252
+ let (_, oft_receipt) = setup.send(&sender, &send_param, &fee, &sender, &quoted_receipt);
253
+
254
+ assert_eq!(oft_receipt.amount_sent_ld, 0);
255
+ assert_eq!(oft_receipt.amount_received_ld, 0);
256
+ }
257
+
258
+ #[test]
259
+ #[should_panic] // just should_panic since SAC and openzeppelin has a different error message
260
+ fn test_send_negative_amount() {
261
+ let env = Env::default();
262
+ let setup = OFTTestSetup::new(&env);
263
+
264
+ let sender = Address::generate(&env);
265
+
266
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
267
+ let dst_eid = 100u32;
268
+ setup.set_peer(dst_eid, &peer);
269
+
270
+ // Fund some tokens and native fees (though sending negative should fail regardless)
271
+ let initial_balance = 100_000_000i128;
272
+ setup.fund_tokens(&sender, initial_balance);
273
+ setup.fund_native_fees(&sender, setup.native_fee);
274
+
275
+ // Attempt to send negative amount - should fail
276
+ // Since Stellar uses i128 for amounts, we test that negative values are properly rejected
277
+ let negative_amount = -12345670i128;
278
+ let send_param = create_send_param(&env, dst_eid, negative_amount, negative_amount);
279
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
280
+ // Create a dummy receipt (will panic before this matters)
281
+ let dummy_receipt = OFTReceipt { amount_sent_ld: negative_amount, amount_received_ld: negative_amount };
282
+
283
+ // This should panic because the token contract rejects negative amounts for burn
284
+ setup.send(&sender, &send_param, &fee, &sender, &dummy_receipt);
285
+ }
286
+
287
+ // ==================== Compose Message Tests ====================
288
+
289
+ #[test]
290
+ fn test_send_with_compose_msg() {
291
+ let env = Env::default();
292
+ let setup = OFTTestSetup::new(&env);
293
+
294
+ let sender = Address::generate(&env);
295
+
296
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
297
+ let dst_eid = 100u32;
298
+ setup.set_peer(dst_eid, &peer);
299
+
300
+ let amount_ld = 12345670i128;
301
+ setup.fund_tokens(&sender, amount_ld);
302
+ setup.fund_native_fees(&sender, setup.native_fee);
303
+
304
+ // Create send param with compose message
305
+ let send_param = SendParam {
306
+ dst_eid,
307
+ to: BytesN::from_array(&env, &[1u8; 32]),
308
+ amount_ld,
309
+ min_amount_ld: amount_ld,
310
+ extra_options: bytes!(&env),
311
+ compose_msg: Bytes::from_array(&env, b"test compose message"),
312
+ oft_cmd: bytes!(&env),
313
+ };
314
+
315
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
316
+ let quoted_receipt = setup.quote_oft(&send_param);
317
+
318
+ let (msg_receipt, oft_receipt) = setup.send(&sender, &send_param, &fee, &sender, &quoted_receipt);
319
+
320
+ // Verify send succeeded
321
+ assert!(msg_receipt.nonce > 0);
322
+ assert_eq!(oft_receipt.amount_sent_ld, amount_ld);
323
+
324
+ // Verify tokens were burned
325
+ assert_eq!(setup.token_client.balance(&sender), 0);
326
+ }
327
+
328
+ // ==================== Event Tests ====================
329
+
330
+ #[test]
331
+ fn test_send_emits_oft_sent_event() {
332
+ let env = Env::default();
333
+ let setup = OFTTestSetup::new(&env);
334
+
335
+ let sender = Address::generate(&env);
336
+
337
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
338
+ let dst_eid = 100u32;
339
+ setup.set_peer(dst_eid, &peer);
340
+
341
+ let amount_ld = 12345670i128;
342
+ setup.fund_tokens(&sender, amount_ld);
343
+ setup.fund_native_fees(&sender, setup.native_fee);
344
+
345
+ let send_param = create_send_param(&env, dst_eid, amount_ld, amount_ld);
346
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
347
+ let quoted_receipt = setup.quote_oft(&send_param);
348
+
349
+ let (msg_receipt, oft_receipt) = setup.send(&sender, &send_param, &fee, &sender, &quoted_receipt);
350
+
351
+ // Assert OFTSent event was emitted with correct values
352
+ assert_event(
353
+ &env,
354
+ &setup.oft.address,
355
+ OFTSent {
356
+ guid: msg_receipt.guid,
357
+ dst_eid,
358
+ from: sender,
359
+ amount_sent_ld: oft_receipt.amount_sent_ld,
360
+ amount_received_ld: oft_receipt.amount_received_ld,
361
+ },
362
+ );
363
+ }
364
+
365
+ // ==================== Multiple Sends Tests ====================
366
+
367
+ #[test]
368
+ fn test_send_multiple_times() {
369
+ let env = Env::default();
370
+ let setup = OFTTestSetup::new(&env);
371
+
372
+ let sender = Address::generate(&env);
373
+
374
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
375
+ let dst_eid = 100u32;
376
+ setup.set_peer(dst_eid, &peer);
377
+
378
+ // Fund enough for multiple sends
379
+ let total_amount = 100_000_000i128;
380
+ let send_amounts = [10_000_000i128, 20_000_000, 30_000_000];
381
+
382
+ setup.fund_tokens(&sender, total_amount);
383
+ setup.fund_native_fees(&sender, setup.native_fee * send_amounts.len() as i128);
384
+
385
+ let mut total_sent = 0i128;
386
+
387
+ for amount in send_amounts.iter() {
388
+ let send_param = create_send_param(&env, dst_eid, *amount, *amount);
389
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
390
+ let quoted_receipt = setup.quote_oft(&send_param);
391
+
392
+ let (msg_receipt, oft_receipt) = setup.send(&sender, &send_param, &fee, &sender, &quoted_receipt);
393
+
394
+ assert_eq!(oft_receipt.amount_sent_ld, *amount);
395
+ assert!(msg_receipt.nonce > 0);
396
+
397
+ total_sent += amount;
398
+ }
399
+
400
+ // Verify remaining balance
401
+ assert_eq!(setup.token_client.balance(&sender), total_amount - total_sent);
402
+ }
403
+
404
+ #[test]
405
+ fn test_send_to_multiple_destinations() {
406
+ let env = Env::default();
407
+ let setup = OFTTestSetup::new(&env);
408
+
409
+ let sender = Address::generate(&env);
410
+
411
+ // Set up multiple peers
412
+ let dst_eids = [1u32, 100, 200, 300];
413
+ for eid in dst_eids.iter() {
414
+ let peer = BytesN::from_array(&env, &[*eid as u8; 32]);
415
+ setup.set_peer(*eid, &peer);
416
+ }
417
+
418
+ // Fund enough for multiple sends
419
+ let total_amount = 100_000_000i128;
420
+ setup.fund_tokens(&sender, total_amount);
421
+ setup.fund_native_fees(&sender, setup.native_fee * dst_eids.len() as i128);
422
+
423
+ let amount_per_send = 10_000_000i128;
424
+ let mut total_sent = 0i128;
425
+
426
+ for dst_eid in dst_eids.iter() {
427
+ let send_param = create_send_param(&env, *dst_eid, amount_per_send, amount_per_send);
428
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
429
+ let quoted_receipt = setup.quote_oft(&send_param);
430
+
431
+ let (_, oft_receipt) = setup.send(&sender, &send_param, &fee, &sender, &quoted_receipt);
432
+
433
+ assert_eq!(oft_receipt.amount_sent_ld, amount_per_send);
434
+ assert_eq!(setup.endpoint_client.get_last_dst_eid(), Some(*dst_eid));
435
+
436
+ total_sent += amount_per_send;
437
+ }
438
+
439
+ // Verify remaining balance
440
+ assert_eq!(setup.token_client.balance(&sender), total_amount - total_sent);
441
+ }
442
+
443
+ // ==================== Different Amounts Tests ====================
444
+
445
+ #[test]
446
+ fn test_send_different_amounts() {
447
+ let env = Env::default();
448
+ let setup = OFTTestSetup::new(&env);
449
+
450
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
451
+ let dst_eid = 100u32;
452
+ setup.set_peer(dst_eid, &peer);
453
+
454
+ // Test with different amounts (all divisible by 10 to avoid dust with SAC's 7 decimals)
455
+ let test_amounts = [10i128, 100, 1000, 10000, 100000, 1_000_000, 10_000_000];
456
+
457
+ for amount in test_amounts.iter() {
458
+ // Generate new sender for each test
459
+ let test_sender = Address::generate(&env);
460
+ setup.fund_tokens(&test_sender, *amount);
461
+ setup.fund_native_fees(&test_sender, setup.native_fee);
462
+
463
+ let send_param = create_send_param(&env, dst_eid, *amount, *amount);
464
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
465
+ let quoted_receipt = setup.quote_oft(&send_param);
466
+
467
+ let (_, oft_receipt) = setup.send(&test_sender, &send_param, &fee, &test_sender, &quoted_receipt);
468
+
469
+ assert_eq!(oft_receipt.amount_sent_ld, *amount);
470
+ assert_eq!(oft_receipt.amount_received_ld, *amount);
471
+ assert_eq!(setup.token_client.balance(&test_sender), 0);
472
+ }
473
+ }
474
+
475
+ #[test]
476
+ fn test_send_large_amount() {
477
+ let env = Env::default();
478
+ let setup = OFTTestSetup::new(&env);
479
+
480
+ let sender = Address::generate(&env);
481
+
482
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
483
+ let dst_eid = 100u32;
484
+ setup.set_peer(dst_eid, &peer);
485
+
486
+ // Large but valid amount (within safe limits)
487
+ // Conversion rate is 10, so max_sd = u64::MAX, max_ld = u64::MAX * 10
488
+ // Use a reasonably large amount
489
+ let large_amount = 1_000_000_000_000_000i128; // 1 quadrillion in local decimals
490
+
491
+ setup.fund_tokens(&sender, large_amount);
492
+ setup.fund_native_fees(&sender, setup.native_fee);
493
+
494
+ let send_param = create_send_param(&env, dst_eid, large_amount, large_amount);
495
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
496
+ let quoted_receipt = setup.quote_oft(&send_param);
497
+
498
+ let (_, oft_receipt) = setup.send(&sender, &send_param, &fee, &sender, &quoted_receipt);
499
+
500
+ assert_eq!(oft_receipt.amount_sent_ld, large_amount);
501
+ assert_eq!(setup.token_client.balance(&sender), 0);
502
+ }
503
+
504
+ // ==================== Fee Tests ====================
505
+
506
+ #[test]
507
+ fn test_send_with_zro_fee() {
508
+ let env = Env::default();
509
+ let setup = OFTTestSetup::new(&env);
510
+
511
+ let sender = Address::generate(&env);
512
+
513
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
514
+ let dst_eid = 100u32;
515
+ setup.set_peer(dst_eid, &peer);
516
+
517
+ let amount_ld = 12345670i128;
518
+ setup.fund_tokens(&sender, amount_ld);
519
+ setup.fund_native_fees(&sender, setup.native_fee);
520
+ setup.fund_zro_fees(&sender, setup.zro_fee);
521
+
522
+ let send_param = create_send_param(&env, dst_eid, amount_ld, amount_ld);
523
+ // Include ZRO fee
524
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: setup.zro_fee };
525
+ let quoted_receipt = setup.quote_oft(&send_param);
526
+
527
+ let (msg_receipt, oft_receipt) = setup.send(&sender, &send_param, &fee, &sender, &quoted_receipt);
528
+
529
+ // Verify receipts
530
+ assert!(msg_receipt.nonce > 0);
531
+ assert_eq!(oft_receipt.amount_sent_ld, amount_ld);
532
+ assert_eq!(setup.token_client.balance(&sender), 0);
533
+ }
534
+
535
+ #[test]
536
+ fn test_send_with_custom_fees() {
537
+ let env = Env::default();
538
+ let custom_native_fee = 2000i128;
539
+ let custom_zro_fee = 750i128;
540
+ let setup = OFTTestSetupBuilder::new(&env).with_fees(custom_native_fee, custom_zro_fee).build();
541
+
542
+ let sender = Address::generate(&env);
543
+
544
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
545
+ let dst_eid = 100u32;
546
+ setup.set_peer(dst_eid, &peer);
547
+
548
+ let amount_ld = 12345670i128;
549
+ setup.fund_tokens(&sender, amount_ld);
550
+ setup.fund_native_fees(&sender, custom_native_fee);
551
+ setup.fund_zro_fees(&sender, custom_zro_fee);
552
+
553
+ let send_param = create_send_param(&env, dst_eid, amount_ld, amount_ld);
554
+ let fee = MessagingFee { native_fee: custom_native_fee, zro_fee: custom_zro_fee };
555
+ let quoted_receipt = setup.quote_oft(&send_param);
556
+
557
+ let (msg_receipt, oft_receipt) = setup.send(&sender, &send_param, &fee, &sender, &quoted_receipt);
558
+
559
+ // Verify receipts with custom fees
560
+ assert!(msg_receipt.nonce > 0);
561
+ assert_eq!(msg_receipt.fee.native_fee, custom_native_fee);
562
+ assert_eq!(msg_receipt.fee.zro_fee, custom_zro_fee);
563
+ assert_eq!(oft_receipt.amount_sent_ld, amount_ld);
564
+ }
565
+
566
+ // ==================== Refund Address Tests ====================
567
+
568
+ #[test]
569
+ fn test_send_with_different_refund_address() {
570
+ let env = Env::default();
571
+ let setup = OFTTestSetup::new(&env);
572
+
573
+ let sender = Address::generate(&env);
574
+ let refund_address = Address::generate(&env);
575
+
576
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
577
+ let dst_eid = 100u32;
578
+ setup.set_peer(dst_eid, &peer);
579
+
580
+ let amount_ld = 12345670i128;
581
+ setup.fund_tokens(&sender, amount_ld);
582
+ setup.fund_native_fees(&sender, setup.native_fee);
583
+
584
+ let send_param = create_send_param(&env, dst_eid, amount_ld, amount_ld);
585
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
586
+ let quoted_receipt = setup.quote_oft(&send_param);
587
+
588
+ // Use different refund address
589
+ let (msg_receipt, oft_receipt) = setup.send(&sender, &send_param, &fee, &refund_address, &quoted_receipt);
590
+
591
+ // Send should still succeed
592
+ assert!(msg_receipt.nonce > 0);
593
+ assert_eq!(oft_receipt.amount_sent_ld, amount_ld);
594
+ assert_eq!(setup.token_client.balance(&sender), 0);
595
+ }
596
+
597
+ // ==================== Lock/Unlock Strategy Tests ====================
598
+
599
+ #[test]
600
+ fn test_send_lock_unlock_strategy() {
601
+ let env = Env::default();
602
+ let setup = OFTTestSetupBuilder::new(&env).lock_unlock().build();
603
+
604
+ let sender = Address::generate(&env);
605
+
606
+ // Set peer
607
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
608
+ let dst_eid = 100u32;
609
+ setup.set_peer(dst_eid, &peer);
610
+
611
+ // SAC has 7 decimals, shared is 6, conversion rate = 10
612
+ // Use amount with no dust
613
+ let amount_ld = 12345670i128;
614
+
615
+ // Fund sender with tokens and native fees
616
+ setup.fund_tokens(&sender, amount_ld);
617
+ setup.fund_native_fees(&sender, setup.native_fee);
618
+ assert_eq!(setup.token_client.balance(&sender), amount_ld);
619
+
620
+ let send_param = create_send_param(&env, dst_eid, amount_ld, amount_ld);
621
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
622
+ let refund_address = sender.clone();
623
+ let oft_receipt = setup.quote_oft(&send_param);
624
+
625
+ // Send tokens
626
+ let (msg_receipt, oft_receipt) = setup.send(&sender, &send_param, &fee, &refund_address, &oft_receipt);
627
+
628
+ // Verify messaging receipt
629
+ assert!(msg_receipt.nonce > 0);
630
+ assert_eq!(msg_receipt.fee.native_fee, setup.native_fee);
631
+
632
+ // Verify OFT receipt
633
+ assert_eq!(oft_receipt.amount_sent_ld, amount_ld);
634
+ assert_eq!(oft_receipt.amount_received_ld, amount_ld);
635
+
636
+ // Verify tokens were burned (MintBurn OFT)
637
+ assert_eq!(setup.token_client.balance(&sender), 0);
638
+
639
+ // Verify endpoint was called
640
+ assert!(setup.endpoint_client.was_sent());
641
+ assert_eq!(setup.endpoint_client.get_last_dst_eid(), Some(dst_eid));
642
+ }
643
+
644
+ // ==================== Authorizations Tests ====================
645
+
646
+ #[test]
647
+ #[should_panic(expected = "HostError: Error(Auth, InvalidAction)")]
648
+ fn test_send_without_giving_authorization() {
649
+ let env = Env::default();
650
+ let setup = OFTTestSetup::new(&env);
651
+
652
+ let sender = Address::generate(&env);
653
+
654
+ // Set peer
655
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
656
+ let dst_eid = 100u32;
657
+ setup.set_peer(dst_eid, &peer);
658
+
659
+ // SAC has 7 decimals, shared is 6, conversion rate = 10
660
+ // Use amount with no dust
661
+ let amount_ld = 12345670i128;
662
+
663
+ // Fund sender with tokens and native fees
664
+ setup.fund_tokens(&sender, amount_ld);
665
+ setup.fund_native_fees(&sender, setup.native_fee);
666
+ assert_eq!(setup.token_client.balance(&sender), amount_ld);
667
+
668
+ let send_param = create_send_param(&env, dst_eid, amount_ld, amount_ld);
669
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
670
+ let refund_address = sender.clone();
671
+
672
+ // Send tokens
673
+ setup.oft.send(&sender, &send_param, &fee, &refund_address);
674
+ }
675
+
676
+ #[test]
677
+ #[should_panic(expected = "HostError: Error(Auth, InvalidAction)")]
678
+ fn test_giving_partial_authorization_without_burn() {
679
+ let env = Env::default();
680
+ let setup = OFTTestSetup::new(&env);
681
+
682
+ let sender = Address::generate(&env);
683
+
684
+ // Set peer
685
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
686
+ let dst_eid = 100u32;
687
+ setup.set_peer(dst_eid, &peer);
688
+
689
+ // SAC has 7 decimals, shared is 6, conversion rate = 10
690
+ // Use amount with no dust
691
+ let amount_ld = 12345670i128;
692
+
693
+ // Fund sender with tokens and native fees
694
+ setup.fund_tokens(&sender, amount_ld);
695
+ setup.fund_native_fees(&sender, setup.native_fee);
696
+ assert_eq!(setup.token_client.balance(&sender), amount_ld);
697
+
698
+ let send_param = create_send_param(&env, dst_eid, amount_ld, amount_ld);
699
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
700
+ let refund_address = sender.clone();
701
+
702
+ // Send tokens
703
+ env.mock_auths(&[MockAuth {
704
+ address: &sender,
705
+ invoke: &MockAuthInvoke {
706
+ contract: &setup.oft.address,
707
+ fn_name: "send",
708
+ args: (&sender, &send_param, &fee, &refund_address).into_val(&env),
709
+ sub_invokes: &[],
710
+ },
711
+ }]);
712
+ setup.oft.send(&sender, &send_param, &fee, &refund_address);
713
+ }
714
+
715
+ #[test]
716
+ #[should_panic(expected = "HostError: Error(Auth, InvalidAction)")]
717
+ fn test_giving_partial_authorization_with_burn_wrong_arguments() {
718
+ let env = Env::default();
719
+ let setup = OFTTestSetup::new(&env);
720
+
721
+ let sender = Address::generate(&env);
722
+
723
+ // Set peer
724
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
725
+ let dst_eid = 100u32;
726
+ setup.set_peer(dst_eid, &peer);
727
+
728
+ // SAC has 7 decimals, shared is 6, conversion rate = 10
729
+ // Use amount with no dust
730
+ let amount_ld = 12345670i128;
731
+
732
+ // Fund sender with tokens and native fees
733
+ setup.fund_tokens(&sender, amount_ld);
734
+ setup.fund_native_fees(&sender, setup.native_fee);
735
+ assert_eq!(setup.token_client.balance(&sender), amount_ld);
736
+
737
+ let send_param = create_send_param(&env, dst_eid, amount_ld, amount_ld);
738
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
739
+ let refund_address = sender.clone();
740
+ let oft_receipt = setup.quote_oft(&send_param);
741
+
742
+ // Send tokens
743
+ env.mock_auths(&[MockAuth {
744
+ address: &sender,
745
+ invoke: &MockAuthInvoke {
746
+ contract: &setup.oft.address,
747
+ fn_name: "send",
748
+ args: (&sender, &send_param, &fee, &refund_address).into_val(&env),
749
+ sub_invokes: &[MockAuthInvoke {
750
+ contract: &setup.token,
751
+ fn_name: "burn",
752
+ args: (&sender, &oft_receipt.amount_sent_ld + 1).into_val(&env),
753
+ sub_invokes: &[],
754
+ }],
755
+ },
756
+ }]);
757
+ setup.oft.send(&sender, &send_param, &fee, &refund_address);
758
+ }
759
+
760
+ #[test]
761
+ #[should_panic(expected = "HostError: Error(Auth, InvalidAction)")]
762
+ fn test_giving_partial_authorization_without_native_fee_authorizations() {
763
+ let env = Env::default();
764
+ let setup = OFTTestSetup::new(&env);
765
+
766
+ let sender = Address::generate(&env);
767
+
768
+ // Set peer
769
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
770
+ let dst_eid = 100u32;
771
+ setup.set_peer(dst_eid, &peer);
772
+
773
+ // SAC has 7 decimals, shared is 6, conversion rate = 10
774
+ // Use amount with no dust
775
+ let amount_ld = 12345670i128;
776
+
777
+ // Fund sender with tokens and native fees
778
+ setup.fund_tokens(&sender, amount_ld);
779
+ setup.fund_native_fees(&sender, setup.native_fee);
780
+ assert_eq!(setup.token_client.balance(&sender), amount_ld);
781
+
782
+ let send_param = create_send_param(&env, dst_eid, amount_ld, amount_ld);
783
+ let fee = MessagingFee { native_fee: setup.native_fee, zro_fee: 0 };
784
+ let refund_address = sender.clone();
785
+ let oft_receipt = setup.quote_oft(&send_param);
786
+
787
+ // Send tokens
788
+ env.mock_auths(&[MockAuth {
789
+ address: &sender,
790
+ invoke: &MockAuthInvoke {
791
+ contract: &setup.oft.address,
792
+ fn_name: "send",
793
+ args: (&sender, &send_param, &fee, &refund_address).into_val(&env),
794
+ sub_invokes: &[MockAuthInvoke {
795
+ contract: &setup.token,
796
+ fn_name: "burn",
797
+ args: (&sender, &oft_receipt.amount_sent_ld).into_val(&env),
798
+ sub_invokes: &[],
799
+ }],
800
+ },
801
+ }]);
802
+ setup.oft.send(&sender, &send_param, &fee, &refund_address);
803
+ }
804
+
805
+ #[test]
806
+ #[should_panic(expected = "HostError: Error(Auth, InvalidAction)")]
807
+ fn test_giving_partial_authorization_without_zro_fee_authorizations() {
808
+ let env = Env::default();
809
+ let setup = OFTTestSetupBuilder::new(&env).with_native_fee(2).with_zro_fee(1).build();
810
+
811
+ let sender = Address::generate(&env);
812
+
813
+ // Set peer
814
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
815
+ let dst_eid = 100u32;
816
+ setup.set_peer(dst_eid, &peer);
817
+
818
+ // SAC has 7 decimals, shared is 6, conversion rate = 10
819
+ // Use amount with no dust
820
+ let amount_ld = 12345670i128;
821
+
822
+ // Fund sender with tokens and native fees
823
+ setup.fund_tokens(&sender, amount_ld);
824
+ setup.fund_native_fees(&sender, setup.native_fee);
825
+ assert_eq!(setup.token_client.balance(&sender), amount_ld);
826
+
827
+ let send_param = create_send_param(&env, dst_eid, amount_ld, amount_ld);
828
+ let refund_address = sender.clone();
829
+ let oft_receipt = setup.quote_oft(&send_param);
830
+ let fee = setup.oft.quote_send(&sender, &send_param, &true);
831
+
832
+ // Send tokens
833
+ env.mock_auths(&[MockAuth {
834
+ address: &sender,
835
+ invoke: &MockAuthInvoke {
836
+ contract: &setup.oft.address,
837
+ fn_name: "send",
838
+ args: (&sender, &send_param, &fee, &refund_address).into_val(&env),
839
+ sub_invokes: &[
840
+ MockAuthInvoke {
841
+ contract: &setup.token,
842
+ fn_name: "burn",
843
+ args: (&sender, &oft_receipt.amount_sent_ld).into_val(&env),
844
+ sub_invokes: &[],
845
+ },
846
+ MockAuthInvoke {
847
+ contract: &setup.native_token,
848
+ fn_name: "transfer",
849
+ args: (&sender, &setup.endpoint_client.address, &fee.native_fee).into_val(&env),
850
+ sub_invokes: &[],
851
+ },
852
+ ],
853
+ },
854
+ }]);
855
+ setup.oft.send(&sender, &send_param, &fee, &refund_address);
856
+ }
857
+
858
+ #[test]
859
+ fn test_giving_full_authorization() {
860
+ let env = Env::default();
861
+ let setup = OFTTestSetupBuilder::new(&env).with_native_fee(2).with_zro_fee(1).build();
862
+
863
+ let sender = Address::generate(&env);
864
+
865
+ // Set peer
866
+ let peer = BytesN::from_array(&env, &[2u8; 32]);
867
+ let dst_eid = 100u32;
868
+ setup.set_peer(dst_eid, &peer);
869
+
870
+ // SAC has 7 decimals, shared is 6, conversion rate = 10
871
+ // Use amount with no dust
872
+ let amount_ld = 12345670i128;
873
+
874
+ // Fund sender with tokens and native fees
875
+ setup.fund_tokens(&sender, amount_ld);
876
+ setup.fund_native_fees(&sender, setup.native_fee);
877
+ setup.fund_zro_fees(&sender, setup.zro_fee);
878
+ assert_eq!(setup.token_client.balance(&sender), amount_ld);
879
+
880
+ let send_param = create_send_param(&env, dst_eid, amount_ld, amount_ld);
881
+ let refund_address = sender.clone();
882
+ let oft_receipt = setup.quote_oft(&send_param);
883
+ let fee = setup.oft.quote_send(&sender, &send_param, &true);
884
+
885
+ // Send tokens
886
+ env.mock_auths(&[MockAuth {
887
+ address: &sender,
888
+ invoke: &MockAuthInvoke {
889
+ contract: &setup.oft.address,
890
+ fn_name: "send",
891
+ args: (&sender, &send_param, &fee, &refund_address).into_val(&env),
892
+ sub_invokes: &[
893
+ MockAuthInvoke {
894
+ contract: &setup.token,
895
+ fn_name: "burn",
896
+ args: (&sender, &oft_receipt.amount_sent_ld).into_val(&env),
897
+ sub_invokes: &[],
898
+ },
899
+ MockAuthInvoke {
900
+ contract: &setup.native_token,
901
+ fn_name: "transfer",
902
+ args: (&sender, &setup.endpoint_client.address, &fee.native_fee).into_val(&env),
903
+ sub_invokes: &[],
904
+ },
905
+ MockAuthInvoke {
906
+ contract: &setup.zro_token,
907
+ fn_name: "transfer",
908
+ args: (&sender, &setup.endpoint_client.address, &fee.zro_fee).into_val(&env),
909
+ sub_invokes: &[],
910
+ },
911
+ ],
912
+ },
913
+ }]);
914
+ setup.oft.send(&sender, &send_param, &fee, &refund_address);
915
+ }