@layerzerolabs/oft-mint-burn-starknet 0.2.9

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 (98) hide show
  1. package/Scarb.lock +190 -0
  2. package/Scarb.toml +3 -0
  3. package/contracts/oft_mint_burn/Scarb.toml +29 -0
  4. package/contracts/oft_mint_burn/src/constants.cairo +11 -0
  5. package/contracts/oft_mint_burn/src/erc20_mint_burn_upgradeable/constants.cairo +17 -0
  6. package/contracts/oft_mint_burn/src/erc20_mint_burn_upgradeable/erc20_mint_burn_upgradeable.cairo +309 -0
  7. package/contracts/oft_mint_burn/src/erc20_mint_burn_upgradeable/interface.cairo +86 -0
  8. package/contracts/oft_mint_burn/src/errors.cairo +39 -0
  9. package/contracts/oft_mint_burn/src/interface.cairo +95 -0
  10. package/contracts/oft_mint_burn/src/lib.cairo +10 -0
  11. package/contracts/oft_mint_burn/src/oft_mint_burn_adapter.cairo +382 -0
  12. package/contracts/oft_mint_burn/tests/fuzzable/contract_address.cairo +21 -0
  13. package/contracts/oft_mint_burn/tests/lib.cairo +8 -0
  14. package/contracts/oft_mint_burn/tests/test_erc20_mint_burn_upgradeable.cairo +621 -0
  15. package/contracts/oft_mint_burn/tests/test_mint_burn_adapter.cairo +194 -0
  16. package/contracts/oft_mint_burn/tests/test_mint_burn_adapter_advanced.cairo +746 -0
  17. package/contracts/oft_mint_burn/tests/utils.cairo +84 -0
  18. package/dist/3UUTAAI4.js +9 -0
  19. package/dist/3UUTAAI4.js.map +1 -0
  20. package/dist/4EGWSIX7.js +18 -0
  21. package/dist/4EGWSIX7.js.map +1 -0
  22. package/dist/54KHZH3Y.cjs +22 -0
  23. package/dist/54KHZH3Y.cjs.map +1 -0
  24. package/dist/5KFUKPR2.js +1033 -0
  25. package/dist/5KFUKPR2.js.map +1 -0
  26. package/dist/5R6WMZVR.cjs +22 -0
  27. package/dist/5R6WMZVR.cjs.map +1 -0
  28. package/dist/CCHLUK5E.cjs +1035 -0
  29. package/dist/CCHLUK5E.cjs.map +1 -0
  30. package/dist/CGU4EJTF.cjs +14 -0
  31. package/dist/CGU4EJTF.cjs.map +1 -0
  32. package/dist/DJIRVXJ3.cjs +1914 -0
  33. package/dist/DJIRVXJ3.cjs.map +1 -0
  34. package/dist/E63KEOR5.cjs +11 -0
  35. package/dist/E63KEOR5.cjs.map +1 -0
  36. package/dist/FL52ASKH.cjs +16 -0
  37. package/dist/FL52ASKH.cjs.map +1 -0
  38. package/dist/GZXOKWQY.js +1303 -0
  39. package/dist/GZXOKWQY.js.map +1 -0
  40. package/dist/IQR2DIUY.cjs +1305 -0
  41. package/dist/IQR2DIUY.cjs.map +1 -0
  42. package/dist/MNNO3GDF.js +14 -0
  43. package/dist/MNNO3GDF.js.map +1 -0
  44. package/dist/NZRVZWHQ.js +1912 -0
  45. package/dist/NZRVZWHQ.js.map +1 -0
  46. package/dist/QYG4SI7W.js +18 -0
  47. package/dist/QYG4SI7W.js.map +1 -0
  48. package/dist/UE6XWQTX.js +12 -0
  49. package/dist/UE6XWQTX.js.map +1 -0
  50. package/dist/generated/abi/e-r-c20-mint-burn-upgradeable.cjs +13 -0
  51. package/dist/generated/abi/e-r-c20-mint-burn-upgradeable.cjs.map +1 -0
  52. package/dist/generated/abi/e-r-c20-mint-burn-upgradeable.d.ts +760 -0
  53. package/dist/generated/abi/e-r-c20-mint-burn-upgradeable.d.ts.map +1 -0
  54. package/dist/generated/abi/e-r-c20-mint-burn-upgradeable.js +4 -0
  55. package/dist/generated/abi/e-r-c20-mint-burn-upgradeable.js.map +1 -0
  56. package/dist/generated/abi/o-f-t-mint-burn-adapter.cjs +13 -0
  57. package/dist/generated/abi/o-f-t-mint-burn-adapter.cjs.map +1 -0
  58. package/dist/generated/abi/o-f-t-mint-burn-adapter.d.ts +1408 -0
  59. package/dist/generated/abi/o-f-t-mint-burn-adapter.d.ts.map +1 -0
  60. package/dist/generated/abi/o-f-t-mint-burn-adapter.js +4 -0
  61. package/dist/generated/abi/o-f-t-mint-burn-adapter.js.map +1 -0
  62. package/dist/generated/abi.cjs +19 -0
  63. package/dist/generated/abi.cjs.map +1 -0
  64. package/dist/generated/abi.d.ts +3 -0
  65. package/dist/generated/abi.d.ts.map +1 -0
  66. package/dist/generated/abi.js +6 -0
  67. package/dist/generated/abi.js.map +1 -0
  68. package/dist/generated/casm.cjs +17 -0
  69. package/dist/generated/casm.cjs.map +1 -0
  70. package/dist/generated/casm.d.ts +3 -0
  71. package/dist/generated/casm.d.ts.map +1 -0
  72. package/dist/generated/casm.js +4 -0
  73. package/dist/generated/casm.js.map +1 -0
  74. package/dist/generated/sierra.cjs +17 -0
  75. package/dist/generated/sierra.cjs.map +1 -0
  76. package/dist/generated/sierra.d.ts +3 -0
  77. package/dist/generated/sierra.d.ts.map +1 -0
  78. package/dist/generated/sierra.js +4 -0
  79. package/dist/generated/sierra.js.map +1 -0
  80. package/dist/generated/verification/index.cjs +14 -0
  81. package/dist/generated/verification/index.cjs.map +1 -0
  82. package/dist/generated/verification/index.d.ts +2 -0
  83. package/dist/generated/verification/index.d.ts.map +1 -0
  84. package/dist/generated/verification/index.js +5 -0
  85. package/dist/generated/verification/index.js.map +1 -0
  86. package/dist/generated/verification/oft_mint_burn.cjs +10 -0
  87. package/dist/generated/verification/oft_mint_burn.cjs.map +1 -0
  88. package/dist/generated/verification/oft_mint_burn.d.ts +4 -0
  89. package/dist/generated/verification/oft_mint_burn.d.ts.map +1 -0
  90. package/dist/generated/verification/oft_mint_burn.js +4 -0
  91. package/dist/generated/verification/oft_mint_burn.js.map +1 -0
  92. package/dist/index.cjs +31 -0
  93. package/dist/index.cjs.map +1 -0
  94. package/dist/index.d.ts +5 -0
  95. package/dist/index.d.ts.map +1 -0
  96. package/dist/index.js +10 -0
  97. package/dist/index.js.map +1 -0
  98. package/package.json +53 -0
@@ -0,0 +1,194 @@
1
+ use core::num::traits::Bounded;
2
+ use layerzero::common::structs::packet::Origin;
3
+ use layerzero::endpoint::interfaces::layerzero_receiver::{
4
+ ILayerZeroReceiverDispatcher, ILayerZeroReceiverDispatcherTrait,
5
+ };
6
+ use layerzero::oapps::oapp::interface::{IOAppDispatcher, IOAppDispatcherTrait};
7
+ use layerzero::oapps::oft::interface::{IOFTDispatcher, IOFTDispatcherTrait};
8
+ use layerzero::oapps::oft::oft_msg_codec::OFTMsgCodec;
9
+ use layerzero::oapps::oft::structs::SendParam;
10
+ use layerzero::{MessageReceipt, MessagingFee};
11
+ use lz_utils::bytes::{Bytes32, ContractAddressIntoBytes32};
12
+ use oft_mint_burn::interface::{IMintableTokenDispatcher, IMintableTokenDispatcherTrait};
13
+ use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait};
14
+ use snforge_std::{start_cheat_caller_address, start_mock_call};
15
+ use starknet::ContractAddress;
16
+ use starkware_utils_testing::test_utils::cheat_caller_address_once;
17
+ use crate::fuzzable::contract_address::FuzzableContractAddress;
18
+ use crate::utils::{
19
+ DIFF_DECIMALS, LZ_ENDPOINT, NATIVE_TOKEN_OWNER, OFTMintBurnAdapterDeploy, OFT_OWNER,
20
+ setup_mint_burn_adapter,
21
+ };
22
+
23
+ #[test]
24
+ #[fuzzer]
25
+ fn test_mint_burn_adapter_send(
26
+ dst_eid: u32,
27
+ peer: u256,
28
+ user: ContractAddress,
29
+ receiver: u256,
30
+ amount_seed: u256,
31
+ send_native_fee: u128,
32
+ user_native_remainder: u128,
33
+ user_erc20_remainder: u128,
34
+ ) {
35
+ // =============================== Transfer parameters =================================
36
+
37
+ let amount_ld = amount_seed % (Bounded::<u64>::MAX.into() * DIFF_DECIMALS);
38
+ let amount_sd: u64 = (amount_ld / DIFF_DECIMALS).try_into().unwrap();
39
+ let dust_ld = amount_ld % DIFF_DECIMALS;
40
+ let clean_amount_ld = amount_ld - dust_ld;
41
+ // Expect a lossless token transfer.
42
+ let min_amount_ld = amount_sd.into() * DIFF_DECIMALS;
43
+
44
+ // Preconditions
45
+ assert_eq!(clean_amount_ld, min_amount_ld);
46
+ assert_gt!(amount_sd, 0); // Hopefully, we never hit 0 of `u64`...
47
+
48
+ // =============================== Setup =================================
49
+
50
+ let OFTMintBurnAdapterDeploy {
51
+ oft_mint_burn_adapter, native_token, erc20_token,
52
+ } = setup_mint_burn_adapter();
53
+
54
+ let oapp_dispatcher = IOAppDispatcher { contract_address: oft_mint_burn_adapter };
55
+
56
+ cheat_caller_address_once(oft_mint_burn_adapter, OFT_OWNER);
57
+ oapp_dispatcher.set_peer(dst_eid, peer.into());
58
+
59
+ // =============================== Send tokens =================================
60
+
61
+ let send_param = SendParam {
62
+ dst_eid,
63
+ to: receiver.into(),
64
+ amount_ld,
65
+ min_amount_ld,
66
+ // not using extra options, compose msg, or oft cmd in this test
67
+ extra_options: Default::default(),
68
+ compose_msg: Default::default(),
69
+ oft_cmd: Default::default(),
70
+ };
71
+
72
+ let balance_ld = amount_ld + user_erc20_remainder.into();
73
+
74
+ // Give user the amount of tokens to send by minting directly to them
75
+ // The OFTMintBurnAdapter will burn these tokens when sending
76
+ // We need to cheat caller address to be the oft_mint_burn_adapter since it has the MINTER_ROLE
77
+ cheat_caller_address_once(erc20_token, oft_mint_burn_adapter);
78
+ IMintableTokenDispatcher { contract_address: erc20_token }.permissioned_mint(user, balance_ld);
79
+
80
+ // Mint native tokens to user for gas fee payment
81
+ cheat_caller_address_once(native_token, NATIVE_TOKEN_OWNER);
82
+ IMintableTokenDispatcher { contract_address: native_token }
83
+ .permissioned_mint(user, send_native_fee.into() + user_native_remainder.into());
84
+
85
+ let pay_in_lz_token = false;
86
+
87
+ // mock endpoint quote call to return the expected send fee
88
+ start_mock_call(
89
+ LZ_ENDPOINT,
90
+ selector!("quote"),
91
+ MessagingFee { native_fee: send_native_fee.into(), lz_token_fee: 0 },
92
+ );
93
+
94
+ // We only quote send since this OFT doesn't have any fees
95
+ let fee = IOFTDispatcher { contract_address: oft_mint_burn_adapter }
96
+ .quote_send(send_param.clone(), pay_in_lz_token);
97
+
98
+ // user has to give allowance to the OFTMintBurnAdapter contract to spend the native fee
99
+ cheat_caller_address_once(native_token, user);
100
+ IERC20Dispatcher { contract_address: native_token }
101
+ .approve(oft_mint_burn_adapter, fee.native_fee);
102
+
103
+ // mock endpoint send call to return the expected message receipt
104
+ // guid nonce and payees are not important for this test
105
+ start_mock_call(
106
+ LZ_ENDPOINT,
107
+ selector!("send"),
108
+ MessageReceipt { guid: Bytes32 { value: 1 }, nonce: 1, payees: array![] },
109
+ );
110
+
111
+ // Refund address is not important for this test since endpoint handles the refund and is mocked
112
+ // here
113
+ cheat_caller_address_once(oft_mint_burn_adapter, user);
114
+ let result = IOFTDispatcher { contract_address: oft_mint_burn_adapter }
115
+ .send(send_param, fee.clone(), user);
116
+
117
+ // =============================== Assertions =================================
118
+
119
+ // User should have sent the amount of tokens to the OFTMintBurnAdapter contract
120
+ let expected_sent_ld = clean_amount_ld;
121
+ let expected_received_ld = clean_amount_ld;
122
+
123
+ assert_eq!(result.oft_receipt.amount_sent_ld, expected_sent_ld);
124
+ assert_eq!(result.oft_receipt.amount_received_ld, expected_received_ld);
125
+
126
+ // Native token should have been approved to endpoint
127
+ // in real endpoint it would have used all the allowance and refunded the remainder
128
+ // but here oapp will have approved the endpoint to spend the native fee
129
+ let approved_after = IERC20Dispatcher { contract_address: native_token }
130
+ .allowance(oft_mint_burn_adapter, LZ_ENDPOINT);
131
+ assert_eq!(fee.native_fee, approved_after);
132
+
133
+ // User should have spent the native fee
134
+ let expected_native_after = IERC20Dispatcher { contract_address: native_token }
135
+ .balance_of(user);
136
+ assert_eq!(expected_native_after, user_native_remainder.into());
137
+
138
+ // User balance of erc20 should have been reduced by the amount of tokens sent
139
+ // it should have received the remainder of the native fee and dust
140
+ let erc20_after = IERC20Dispatcher { contract_address: erc20_token }.balance_of(user);
141
+ assert_eq!(user_erc20_remainder.into() + dust_ld, erc20_after);
142
+
143
+ // check erc20 total supply to ensure tokens were burned
144
+ let total_supply = IERC20Dispatcher { contract_address: erc20_token }.total_supply();
145
+ assert_eq!(total_supply, user_erc20_remainder.into() + dust_ld);
146
+ }
147
+
148
+
149
+ #[test]
150
+ #[fuzzer]
151
+ fn test_mint_burn_adapter_receive(
152
+ src_eid: u32,
153
+ sender: u256,
154
+ nonce: u64,
155
+ guid: u256,
156
+ receiver: ContractAddress,
157
+ amount_sd: u64,
158
+ executor: ContractAddress,
159
+ ) {
160
+ // =============================== Parameters =================================
161
+ let receiver_bytes32: Bytes32 = receiver.into();
162
+ let expected_amount_ld: u256 = amount_sd.into() * DIFF_DECIMALS;
163
+ let origin = Origin { src_eid, sender: sender.into(), nonce };
164
+
165
+ // not using compose msg in this test
166
+ let (message, _) = OFTMsgCodec::encode(receiver_bytes32, amount_sd, @"");
167
+
168
+ // =============================== Setup =================================
169
+
170
+ let OFTMintBurnAdapterDeploy {
171
+ oft_mint_burn_adapter, erc20_token, ..,
172
+ } = setup_mint_burn_adapter();
173
+
174
+ // setup_peer
175
+ cheat_caller_address_once(oft_mint_burn_adapter, OFT_OWNER);
176
+ IOAppDispatcher { contract_address: oft_mint_burn_adapter }.set_peer(src_eid, sender.into());
177
+
178
+ // =============================== Receive tokens =================================
179
+
180
+ // Cheat caller address to endpoint since it is the one calling lz_receive
181
+ start_cheat_caller_address(oft_mint_burn_adapter, LZ_ENDPOINT);
182
+ ILayerZeroReceiverDispatcher { contract_address: oft_mint_burn_adapter }
183
+ .lz_receive(origin, guid.into(), message, executor, Default::default(), 0);
184
+
185
+ // =============================== Assertions =================================
186
+
187
+ // User should have received the amount of tokens
188
+ let received_ld = IERC20Dispatcher { contract_address: erc20_token }.balance_of(receiver);
189
+ assert_eq!(expected_amount_ld, received_ld);
190
+
191
+ // check erc20 total supply to ensure tokens were minted
192
+ let total_supply = IERC20Dispatcher { contract_address: erc20_token }.total_supply();
193
+ assert_eq!(total_supply, expected_amount_ld);
194
+ }