@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.
- package/Scarb.lock +190 -0
- package/Scarb.toml +3 -0
- package/contracts/oft_mint_burn/Scarb.toml +29 -0
- package/contracts/oft_mint_burn/src/constants.cairo +11 -0
- package/contracts/oft_mint_burn/src/erc20_mint_burn_upgradeable/constants.cairo +17 -0
- package/contracts/oft_mint_burn/src/erc20_mint_burn_upgradeable/erc20_mint_burn_upgradeable.cairo +309 -0
- package/contracts/oft_mint_burn/src/erc20_mint_burn_upgradeable/interface.cairo +86 -0
- package/contracts/oft_mint_burn/src/errors.cairo +39 -0
- package/contracts/oft_mint_burn/src/interface.cairo +95 -0
- package/contracts/oft_mint_burn/src/lib.cairo +10 -0
- package/contracts/oft_mint_burn/src/oft_mint_burn_adapter.cairo +382 -0
- package/contracts/oft_mint_burn/tests/fuzzable/contract_address.cairo +21 -0
- package/contracts/oft_mint_burn/tests/lib.cairo +8 -0
- package/contracts/oft_mint_burn/tests/test_erc20_mint_burn_upgradeable.cairo +621 -0
- package/contracts/oft_mint_burn/tests/test_mint_burn_adapter.cairo +194 -0
- package/contracts/oft_mint_burn/tests/test_mint_burn_adapter_advanced.cairo +746 -0
- package/contracts/oft_mint_burn/tests/utils.cairo +84 -0
- package/dist/3UUTAAI4.js +9 -0
- package/dist/3UUTAAI4.js.map +1 -0
- package/dist/4EGWSIX7.js +18 -0
- package/dist/4EGWSIX7.js.map +1 -0
- package/dist/54KHZH3Y.cjs +22 -0
- package/dist/54KHZH3Y.cjs.map +1 -0
- package/dist/5KFUKPR2.js +1033 -0
- package/dist/5KFUKPR2.js.map +1 -0
- package/dist/5R6WMZVR.cjs +22 -0
- package/dist/5R6WMZVR.cjs.map +1 -0
- package/dist/CCHLUK5E.cjs +1035 -0
- package/dist/CCHLUK5E.cjs.map +1 -0
- package/dist/CGU4EJTF.cjs +14 -0
- package/dist/CGU4EJTF.cjs.map +1 -0
- package/dist/DJIRVXJ3.cjs +1914 -0
- package/dist/DJIRVXJ3.cjs.map +1 -0
- package/dist/E63KEOR5.cjs +11 -0
- package/dist/E63KEOR5.cjs.map +1 -0
- package/dist/FL52ASKH.cjs +16 -0
- package/dist/FL52ASKH.cjs.map +1 -0
- package/dist/GZXOKWQY.js +1303 -0
- package/dist/GZXOKWQY.js.map +1 -0
- package/dist/IQR2DIUY.cjs +1305 -0
- package/dist/IQR2DIUY.cjs.map +1 -0
- package/dist/MNNO3GDF.js +14 -0
- package/dist/MNNO3GDF.js.map +1 -0
- package/dist/NZRVZWHQ.js +1912 -0
- package/dist/NZRVZWHQ.js.map +1 -0
- package/dist/QYG4SI7W.js +18 -0
- package/dist/QYG4SI7W.js.map +1 -0
- package/dist/UE6XWQTX.js +12 -0
- package/dist/UE6XWQTX.js.map +1 -0
- package/dist/generated/abi/e-r-c20-mint-burn-upgradeable.cjs +13 -0
- package/dist/generated/abi/e-r-c20-mint-burn-upgradeable.cjs.map +1 -0
- package/dist/generated/abi/e-r-c20-mint-burn-upgradeable.d.ts +760 -0
- package/dist/generated/abi/e-r-c20-mint-burn-upgradeable.d.ts.map +1 -0
- package/dist/generated/abi/e-r-c20-mint-burn-upgradeable.js +4 -0
- package/dist/generated/abi/e-r-c20-mint-burn-upgradeable.js.map +1 -0
- package/dist/generated/abi/o-f-t-mint-burn-adapter.cjs +13 -0
- package/dist/generated/abi/o-f-t-mint-burn-adapter.cjs.map +1 -0
- package/dist/generated/abi/o-f-t-mint-burn-adapter.d.ts +1408 -0
- package/dist/generated/abi/o-f-t-mint-burn-adapter.d.ts.map +1 -0
- package/dist/generated/abi/o-f-t-mint-burn-adapter.js +4 -0
- package/dist/generated/abi/o-f-t-mint-burn-adapter.js.map +1 -0
- package/dist/generated/abi.cjs +19 -0
- package/dist/generated/abi.cjs.map +1 -0
- package/dist/generated/abi.d.ts +3 -0
- package/dist/generated/abi.d.ts.map +1 -0
- package/dist/generated/abi.js +6 -0
- package/dist/generated/abi.js.map +1 -0
- package/dist/generated/casm.cjs +17 -0
- package/dist/generated/casm.cjs.map +1 -0
- package/dist/generated/casm.d.ts +3 -0
- package/dist/generated/casm.d.ts.map +1 -0
- package/dist/generated/casm.js +4 -0
- package/dist/generated/casm.js.map +1 -0
- package/dist/generated/sierra.cjs +17 -0
- package/dist/generated/sierra.cjs.map +1 -0
- package/dist/generated/sierra.d.ts +3 -0
- package/dist/generated/sierra.d.ts.map +1 -0
- package/dist/generated/sierra.js +4 -0
- package/dist/generated/sierra.js.map +1 -0
- package/dist/generated/verification/index.cjs +14 -0
- package/dist/generated/verification/index.cjs.map +1 -0
- package/dist/generated/verification/index.d.ts +2 -0
- package/dist/generated/verification/index.d.ts.map +1 -0
- package/dist/generated/verification/index.js +5 -0
- package/dist/generated/verification/index.js.map +1 -0
- package/dist/generated/verification/oft_mint_burn.cjs +10 -0
- package/dist/generated/verification/oft_mint_burn.cjs.map +1 -0
- package/dist/generated/verification/oft_mint_burn.d.ts +4 -0
- package/dist/generated/verification/oft_mint_burn.d.ts.map +1 -0
- package/dist/generated/verification/oft_mint_burn.js +4 -0
- package/dist/generated/verification/oft_mint_burn.js.map +1 -0
- package/dist/index.cjs +31 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- 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
|
+
}
|