git.delta.rocks / unique-network / refs/commits / c9c7549767f0

difftreelog

feature: make collection creation methods `payable`

Grigoriy Simonov2022-09-30parent: #fea73f4.patch.diff
in: master

19 files changed

modifiedcrates/evm-coder/procedural/src/solidity_interface.rsdiffbeforeafterboth
560 selector: u32,560 selector: u32,
561 args: Vec<MethodArg>,561 args: Vec<MethodArg>,
562 has_normal_args: bool,562 has_normal_args: bool,
563 has_value_args: bool,
563 mutability: Mutability,564 mutability: Mutability,
564 result: Type,565 result: Type,
565 weight: Option<Expr>,566 weight: Option<Expr>,
647 .unwrap_or_else(|| cases::camelcase::to_camel_case(&ident.to_string()));648 .unwrap_or_else(|| cases::camelcase::to_camel_case(&ident.to_string()));
648 let mut selector_str = camel_name.clone();649 let mut selector_str = camel_name.clone();
649 selector_str.push('(');650 selector_str.push('(');
651 let mut normal_args_count = 0u32;
650 let mut has_normal_args = false;652 let mut has_value_args = false;
651 for (i, arg) in args.iter().filter(|arg| !arg.is_special()).enumerate() {653 for arg in args.iter() {
654 if arg.is_value() {
655 has_value_args = true;
656 } else if !arg.is_special() {
652 if i != 0 {657 if normal_args_count != 0 {
653 selector_str.push(',');658 selector_str.push(',');
654 }659 }
655 write!(selector_str, "{}", arg.selector_ty()).unwrap();660 write!(selector_str, "{}", arg.selector_ty()).unwrap();
656 has_normal_args = true;661 normal_args_count = normal_args_count.saturating_add(1);
657 }662 }
663 }
664 let has_normal_args = normal_args_count > 0;
658 selector_str.push(')');665 selector_str.push(')');
659 let selector = fn_selector_str(&selector_str);666 let selector = fn_selector_str(&selector_str);
660667
667 selector,674 selector,
668 args,675 args,
669 has_normal_args,676 has_normal_args,
677 has_value_args,
670 mutability,678 mutability,
671 result: result.clone(),679 result: result.clone(),
672 weight,680 weight,
823 let docs = &self.docs;831 let docs = &self.docs;
824 let selector_str = &self.selector_str;832 let selector_str = &self.selector_str;
825 let selector = self.selector;833 let selector = self.selector;
826834 let is_payable = self.has_value_args;
827 quote! {835 quote! {
828 SolidityFunction {836 SolidityFunction {
829 docs: &[#(#docs),*],837 docs: &[#(#docs),*],
830 selector_str: #selector_str,838 selector_str: #selector_str,
831 selector: #selector,839 selector: #selector,
832 name: #camel_name,840 name: #camel_name,
833 mutability: #mutability,841 mutability: #mutability,
842 is_payable: #is_payable,
834 args: (843 args: (
835 #(844 #(
836 #args,845 #args,
modifiedcrates/evm-coder/src/solidity.rsdiffbeforeafterboth
422 pub args: A,422 pub args: A,
423 pub result: R,423 pub result: R,
424 pub mutability: SolidityMutability,424 pub mutability: SolidityMutability,
425 pub is_payable: bool,
425}426}
426impl<A: SolidityArguments, R: SolidityArguments> SolidityFunctions for SolidityFunction<A, R> {427impl<A: SolidityArguments, R: SolidityArguments> SolidityFunctions for SolidityFunction<A, R> {
427 fn solidity_name(428 fn solidity_name(
452 SolidityMutability::View => write!(writer, " view")?,453 SolidityMutability::View => write!(writer, " view")?,
453 SolidityMutability::Mutable => {}454 SolidityMutability::Mutable => {}
454 }455 }
456 if self.is_payable {
457 write!(writer, " payable")?;
458 }
455 if !self.result.is_empty() {459 if !self.result.is_empty() {
456 write!(writer, " returns (")?;460 write!(writer, " returns (")?;
457 self.result.solidity_name(writer, tc)?;461 self.result.solidity_name(writer, tc)?;
modifiedpallets/common/src/dispatch.rsdiffbeforeafterboth
78 /// * `data` - Description of the created collection.78 /// * `data` - Description of the created collection.
79 fn create(79 fn create(
80 sender: T::CrossAccountId,80 sender: T::CrossAccountId,
81 payer: T::CrossAccountId,
81 data: CreateCollectionData<T::AccountId>,82 data: CreateCollectionData<T::AccountId>,
82 ) -> Result<CollectionId, DispatchError>;83 ) -> Result<CollectionId, DispatchError>;
8384
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
866 /// * `flags` - Extra flags to store.866 /// * `flags` - Extra flags to store.
867 pub fn init_collection(867 pub fn init_collection(
868 owner: T::CrossAccountId,868 owner: T::CrossAccountId,
869 payer: T::CrossAccountId,
869 data: CreateCollectionData<T::AccountId>,870 data: CreateCollectionData<T::AccountId>,
870 flags: CollectionFlags,871 flags: CollectionFlags,
871 ) -> Result<CollectionId, DispatchError> {872 ) -> Result<CollectionId, DispatchError> {
939 ),940 ),
940 );941 );
941 <T as Config>::Currency::settle(942 <T as Config>::Currency::settle(
942 owner.as_sub(),943 payer.as_sub(),
943 imbalance,944 imbalance,
944 WithdrawReasons::TRANSFER,945 WithdrawReasons::TRANSFER,
945 ExistenceRequirement::KeepAlive,946 ExistenceRequirement::KeepAlive,
modifiedpallets/foreign-assets/src/lib.rsdiffbeforeafterboth
309 mode: CollectionMode::Fungible(md.decimals),309 mode: CollectionMode::Fungible(md.decimals),
310 ..Default::default()310 ..Default::default()
311 };311 };
312312 let owner = T::CrossAccountId::from_sub(owner);
313 let bounded_collection_id = <PalletFungible<T>>::init_foreign_collection(313 let bounded_collection_id = <PalletFungible<T>>::init_foreign_collection(
314 CrossAccountId::from_sub(owner),314 owner.clone(),
315 owner,
315 data,316 data,
316 )?;317 )?;
317 let foreign_asset_id =318 let foreign_asset_id =
modifiedpallets/fungible/src/lib.rsdiffbeforeafterboth
210 /// Initializes the collection. Returns [CollectionId] on success, [DispatchError] otherwise.210 /// Initializes the collection. Returns [CollectionId] on success, [DispatchError] otherwise.
211 pub fn init_collection(211 pub fn init_collection(
212 owner: T::CrossAccountId,212 owner: T::CrossAccountId,
213 payer: T::CrossAccountId,
213 data: CreateCollectionData<T::AccountId>,214 data: CreateCollectionData<T::AccountId>,
214 ) -> Result<CollectionId, DispatchError> {215 ) -> Result<CollectionId, DispatchError> {
215 <PalletCommon<T>>::init_collection(owner, data, CollectionFlags::default())216 <PalletCommon<T>>::init_collection(owner, payer, data, CollectionFlags::default())
216 }217 }
217218
218 /// Initializes the collection with ForeignCollection flag. Returns [CollectionId] on success, [DispatchError] otherwise.219 /// Initializes the collection with ForeignCollection flag. Returns [CollectionId] on success, [DispatchError] otherwise.
219 pub fn init_foreign_collection(220 pub fn init_foreign_collection(
220 owner: T::CrossAccountId,221 owner: T::CrossAccountId,
222 payer: T::CrossAccountId,
221 data: CreateCollectionData<T::AccountId>,223 data: CreateCollectionData<T::AccountId>,
222 ) -> Result<CollectionId, DispatchError> {224 ) -> Result<CollectionId, DispatchError> {
223 let id = <PalletCommon<T>>::init_collection(225 let id = <PalletCommon<T>>::init_collection(
224 owner,226 owner,
227 payer,
225 data,228 data,
226 CollectionFlags {229 CollectionFlags {
227 foreign: true,230 foreign: true,
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
405 /// - `data`: Contains settings for collection limits and permissions.405 /// - `data`: Contains settings for collection limits and permissions.
406 pub fn init_collection(406 pub fn init_collection(
407 owner: T::CrossAccountId,407 owner: T::CrossAccountId,
408 payer: T::CrossAccountId,
408 data: CreateCollectionData<T::AccountId>,409 data: CreateCollectionData<T::AccountId>,
409 is_external: bool,410 is_external: bool,
410 ) -> Result<CollectionId, DispatchError> {411 ) -> Result<CollectionId, DispatchError> {
411 <PalletCommon<T>>::init_collection(412 <PalletCommon<T>>::init_collection(
412 owner,413 owner,
414 payer,
413 data,415 data,
414 CollectionFlags {416 CollectionFlags {
415 external: is_external,417 external: is_external,
modifiedpallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth
1448 data: CreateCollectionData<T::AccountId>,1448 data: CreateCollectionData<T::AccountId>,
1449 properties: impl Iterator<Item = Property>,1449 properties: impl Iterator<Item = Property>,
1450 ) -> Result<CollectionId, DispatchError> {1450 ) -> Result<CollectionId, DispatchError> {
1451 let collection_id = <PalletNft<T>>::init_collection(sender, data, true);1451 let collection_id = <PalletNft<T>>::init_collection(sender.clone(), sender, data, true);
14521452
1453 if let Err(DispatchError::Arithmetic(_)) = &collection_id {1453 if let Err(DispatchError::Arithmetic(_)) = &collection_id {
1454 return Err(<Error<T>>::NoAvailableCollectionId.into());1454 return Err(<Error<T>>::NoAvailableCollectionId.into());
modifiedpallets/proxy-rmrk-equip/src/lib.rsdiffbeforeafterboth
251 };251 };
252252
253 let collection_id_res =253 let collection_id_res =
254 <PalletNft<T>>::init_collection(cross_sender.clone(), data, true);254 <PalletNft<T>>::init_collection(cross_sender.clone(), cross_sender.clone(), data, true);
255255
256 if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {256 if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {
257 return Err(<Error<T>>::NoAvailableBaseId.into());257 return Err(<Error<T>>::NoAvailableBaseId.into());
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
373 /// - `data`: Contains settings for collection limits and permissions.373 /// - `data`: Contains settings for collection limits and permissions.
374 pub fn init_collection(374 pub fn init_collection(
375 owner: T::CrossAccountId,375 owner: T::CrossAccountId,
376 payer: T::CrossAccountId,
376 data: CreateCollectionData<T::AccountId>,377 data: CreateCollectionData<T::AccountId>,
377 ) -> Result<CollectionId, DispatchError> {378 ) -> Result<CollectionId, DispatchError> {
378 <PalletCommon<T>>::init_collection(owner, data, CollectionFlags::default())379 <PalletCommon<T>>::init_collection(owner, payer, data, CollectionFlags::default())
379 }380 }
380381
381 /// Destroy RFT collection382 /// Destroy RFT collection
modifiedpallets/unique/src/eth/mod.rsdiffbeforeafterboth
28 static_property::{key, value as property_value},28 static_property::{key, value as property_value},
29 },29 },
30};30};
31use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};31use pallet_evm_coder_substrate::{dispatch_to_evm, SubstrateRecorder, WithRecorder};
32use pallet_evm::{account::CrossAccountId, OnMethodCall, PrecompileHandle, PrecompileResult};32use pallet_evm::{account::CrossAccountId, OnMethodCall, PrecompileHandle, PrecompileResult};
33use up_data_structs::{33use up_data_structs::{
34 CollectionName, CollectionDescription, CollectionTokenPrefix, CreateCollectionData,34 CollectionName, CollectionDescription, CollectionTokenPrefix, CreateCollectionData,
156 T: Config + pallet_nonfungible::Config + pallet_refungible::Config,156 T: Config + pallet_nonfungible::Config + pallet_refungible::Config,
157>(157>(
158 caller: caller,158 caller: caller,
159 value: value,
159 name: string,160 name: string,
160 description: string,161 description: string,
161 token_prefix: string,162 token_prefix: string,
172 base_uri_value,173 base_uri_value,
173 add_properties,174 add_properties,
174 )?;175 )?;
176 let value = value.as_u128();
177 let creation_price: Result<u128> = T::CollectionCreationPrice::get()
178 .try_into()
179 .map_err(|_| "collection creation price should be convertible to u128".into());
180 if value != creation_price? {
181 return Err("Sent amount not equals to collection creation price".into());
182 }
183 let collection_helpers_address = T::CrossAccountId::from_eth(<T as pallet_common::Config>::ContractAddress::get());
175184
176 let collection_id = T::CollectionDispatch::create(caller.clone(), data)185 let collection_id = T::CollectionDispatch::create(caller.clone(), collection_helpers_address, data)
177 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;186 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;
178 let address = pallet_common::eth::collection_id_to_address(collection_id);187 let address = pallet_common::eth::collection_id_to_address(collection_id);
179 Ok(address)188 Ok(address)
183#[solidity_interface(name = CollectionHelpers, events(CollectionHelpersEvents))]192#[solidity_interface(name = CollectionHelpers, events(CollectionHelpersEvents))]
184impl<T> EvmCollectionHelpers<T>193impl<T> EvmCollectionHelpers<T>
185where194where
186 T: Config + pallet_nonfungible::Config + pallet_refungible::Config,195 T: Config + pallet_common::Config + pallet_nonfungible::Config + pallet_refungible::Config,
187{196{
188 /// Create an NFT collection197 /// Create an NFT collection
189 /// @param name Name of the collection198 /// @param name Name of the collection
209 Default::default(),218 Default::default(),
210 false,219 false,
211 )?;220 )?;
221 let value = value.as_u128();
222 let creation_price: Result<u128> = T::CollectionCreationPrice::get()
223 .try_into()
224 .map_err(|_| "collection creation price should be convertible to u128".into());
225 let creation_price = creation_price?;
226 if value != creation_price {
227 return Err(format!("Sent amount not equals to collection creation price ({0})", creation_price).into());
228 }
229 let collection_helpers_address = T::CrossAccountId::from_eth(<T as pallet_common::Config>::ContractAddress::get());
212 let collection_id = T::CollectionDispatch::create(caller, data)230 let collection_id =
213 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;231 T::CollectionDispatch::create(caller, collection_helpers_address, data).map_err(dispatch_to_evm::<T>)?;
214232
215 let address = pallet_common::eth::collection_id_to_address(collection_id);233 let address = pallet_common::eth::collection_id_to_address(collection_id);
216 Ok(address)234 Ok(address)
221 fn create_nonfungible_collection_with_properties(239 fn create_nonfungible_collection_with_properties(
222 &mut self,240 &mut self,
223 caller: caller,241 caller: caller,
242 value: value,
224 name: string,243 name: string,
225 description: string,244 description: string,
226 token_prefix: string,245 token_prefix: string,
236 base_uri_value,255 base_uri_value,
237 true,256 true,
238 )?;257 )?;
258 let value = value.as_u128();
259 let creation_price: Result<u128> = T::CollectionCreationPrice::get()
260 .try_into()
261 .map_err(|_| "collection creation price should be convertible to u128".into());
262 if value != creation_price? {
263 return Err("Sent amount not equals to collection creation price".into());
264 }
265 let collection_helpers_address = T::CrossAccountId::from_eth(<T as pallet_common::Config>::ContractAddress::get());
239 let collection_id = T::CollectionDispatch::create(caller, data)266 let collection_id = T::CollectionDispatch::create(caller, collection_helpers_address, data)
240 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;267 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;
241268
242 let address = pallet_common::eth::collection_id_to_address(collection_id);269 let address = pallet_common::eth::collection_id_to_address(collection_id);
248 fn create_refungible_collection(275 fn create_refungible_collection(
249 &mut self,276 &mut self,
250 caller: caller,277 caller: caller,
278 value: value,
251 name: string,279 name: string,
252 description: string,280 description: string,
253 token_prefix: string,281 token_prefix: string,
254 ) -> Result<address> {282 ) -> Result<address> {
255 create_refungible_collection_internal::<T>(283 create_refungible_collection_internal::<T>(
256 caller,284 caller,
285 value,
257 name,286 name,
258 description,287 description,
259 token_prefix,288 token_prefix,
267 fn create_refungible_collection_with_properties(296 fn create_refungible_collection_with_properties(
268 &mut self,297 &mut self,
269 caller: caller,298 caller: caller,
299 value: value,
270 name: string,300 name: string,
271 description: string,301 description: string,
272 token_prefix: string,302 token_prefix: string,
273 base_uri: string,303 base_uri: string,
274 ) -> Result<address> {304 ) -> Result<address> {
275 create_refungible_collection_internal::<T>(305 create_refungible_collection_internal::<T>(
276 caller,306 caller,
307 value,
277 name,308 name,
278 description,309 description,
279 token_prefix,310 token_prefix,
modifiedpallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/unique/src/eth/stubs/CollectionHelpers.soldiffbeforeafterboth
36 string memory name,36 string memory name,
37 string memory description,37 string memory description,
38 string memory tokenPrefix38 string memory tokenPrefix
39 ) public returns (address) {39 ) public payable returns (address) {
40 require(false, stub_error);40 require(false, stub_error);
41 name;41 name;
42 description;42 description;
52 string memory description,52 string memory description,
53 string memory tokenPrefix,53 string memory tokenPrefix,
54 string memory baseUri54 string memory baseUri
55 ) public returns (address) {55 ) public payable returns (address) {
56 require(false, stub_error);56 require(false, stub_error);
57 name;57 name;
58 description;58 description;
68 string memory name,68 string memory name,
69 string memory description,69 string memory description,
70 string memory tokenPrefix70 string memory tokenPrefix
71 ) public returns (address) {71 ) public payable returns (address) {
72 require(false, stub_error);72 require(false, stub_error);
73 name;73 name;
74 description;74 description;
84 string memory description,84 string memory description,
85 string memory tokenPrefix,85 string memory tokenPrefix,
86 string memory baseUri86 string memory baseUri
87 ) public returns (address) {87 ) public payable returns (address) {
88 require(false, stub_error);88 require(false, stub_error);
89 name;89 name;
90 description;90 description;
modifiedpallets/unique/src/lib.rsdiffbeforeafterboth
344 let sender = ensure_signed(origin)?;344 let sender = ensure_signed(origin)?;
345345
346 // =========346 // =========
347347 let sender = T::CrossAccountId::from_sub(sender);
348 let _id = T::CollectionDispatch::create(T::CrossAccountId::from_sub(sender), data)?;348 let _id = T::CollectionDispatch::create(sender.clone(), sender, data)?;
349349
350 Ok(())350 Ok(())
351 }351 }
modifiedruntime/common/dispatch.rsdiffbeforeafterboth
55{55{
56 fn create(56 fn create(
57 sender: T::CrossAccountId,57 sender: T::CrossAccountId,
58 payer: T::CrossAccountId,
58 data: CreateCollectionData<T::AccountId>,59 data: CreateCollectionData<T::AccountId>,
59 ) -> Result<CollectionId, DispatchError> {60 ) -> Result<CollectionId, DispatchError> {
60 let id = match data.mode {61 let id = match data.mode {
61 CollectionMode::NFT => <PalletNonfungible<T>>::init_collection(sender, data, false)?,62 CollectionMode::NFT => <PalletNonfungible<T>>::init_collection(sender, payer, data, false)?,
62 CollectionMode::Fungible(decimal_points) => {63 CollectionMode::Fungible(decimal_points) => {
63 // check params64 // check params
64 ensure!(65 ensure!(
65 decimal_points <= MAX_DECIMAL_POINTS,66 decimal_points <= MAX_DECIMAL_POINTS,
66 pallet_unique::Error::<T>::CollectionDecimalPointLimitExceeded67 pallet_unique::Error::<T>::CollectionDecimalPointLimitExceeded
67 );68 );
68 <PalletFungible<T>>::init_collection(sender, data)?69 <PalletFungible<T>>::init_collection(sender, payer, data)?
69 }70 }
7071
71 #[cfg(feature = "refungible")]72 #[cfg(feature = "refungible")]
72 CollectionMode::ReFungible => <PalletRefungible<T>>::init_collection(sender, data)?,73 CollectionMode::ReFungible => <PalletRefungible<T>>::init_collection(sender, payer, data)?,
7374
74 #[cfg(not(feature = "refungible"))]75 #[cfg(not(feature = "refungible"))]
75 CollectionMode::ReFungible => return unsupported!(T),76 CollectionMode::ReFungible => return unsupported!(T),
modifiedtests/src/eth/api/CollectionHelpers.soldiffbeforeafterboth
31 string memory name,31 string memory name,
32 string memory description,32 string memory description,
33 string memory tokenPrefix33 string memory tokenPrefix
34 ) external returns (address);34 ) external payable returns (address);
3535
36 /// @dev EVM selector for this function is: 0xa634a5f9,36 /// @dev EVM selector for this function is: 0xa634a5f9,
37 /// or in textual repr: createERC721MetadataCompatibleCollection(string,string,string,string)37 /// or in textual repr: createERC721MetadataCompatibleCollection(string,string,string,string)
40 string memory description,40 string memory description,
41 string memory tokenPrefix,41 string memory tokenPrefix,
42 string memory baseUri42 string memory baseUri
43 ) external returns (address);43 ) external payable returns (address);
4444
45 /// @dev EVM selector for this function is: 0xab173450,45 /// @dev EVM selector for this function is: 0xab173450,
46 /// or in textual repr: createRFTCollection(string,string,string)46 /// or in textual repr: createRFTCollection(string,string,string)
47 function createRFTCollection(47 function createRFTCollection(
48 string memory name,48 string memory name,
49 string memory description,49 string memory description,
50 string memory tokenPrefix50 string memory tokenPrefix
51 ) external returns (address);51 ) external payable returns (address);
5252
53 /// @dev EVM selector for this function is: 0xa5596388,53 /// @dev EVM selector for this function is: 0xa5596388,
54 /// or in textual repr: createERC721MetadataCompatibleRFTCollection(string,string,string,string)54 /// or in textual repr: createERC721MetadataCompatibleRFTCollection(string,string,string,string)
57 string memory description,57 string memory description,
58 string memory tokenPrefix,58 string memory tokenPrefix,
59 string memory baseUri59 string memory baseUri
60 ) external returns (address);60 ) external payable returns (address);
6161
62 /// Check if a collection exists62 /// Check if a collection exists
63 /// @param collectionAddress Address of the collection in question63 /// @param collectionAddress Address of the collection in question
modifiedtests/src/eth/collectionHelpersAbi.jsondiffbeforeafterboth
27 ],27 ],
28 "name": "createERC721MetadataCompatibleCollection",28 "name": "createERC721MetadataCompatibleCollection",
29 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],29 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
30 "stateMutability": "nonpayable",30 "stateMutability": "payable",
31 "type": "function"31 "type": "function"
32 },32 },
33 {33 {
39 ],39 ],
40 "name": "createERC721MetadataCompatibleRFTCollection",40 "name": "createERC721MetadataCompatibleRFTCollection",
41 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],41 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
42 "stateMutability": "nonpayable",42 "stateMutability": "payable",
43 "type": "function"43 "type": "function"
44 },44 },
45 {45 {
50 ],50 ],
51 "name": "createNonfungibleCollection",51 "name": "createNonfungibleCollection",
52 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],52 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
53 "stateMutability": "nonpayable",53 "stateMutability": "payable",
54 "type": "function"54 "type": "function"
55 },55 },
56 {56 {
61 ],61 ],
62 "name": "createRFTCollection",62 "name": "createRFTCollection",
63 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],63 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
64 "stateMutability": "nonpayable",64 "stateMutability": "payable",
65 "type": "function"65 "type": "function"
66 },66 },
67 {67 {
modifiedtests/src/eth/fractionalizer/Fractionalizer.soldiffbeforeafterboth
18 mapping(address => bool) nftCollectionAllowList;18 mapping(address => bool) nftCollectionAllowList;
19 mapping(address => mapping(uint256 => uint256)) public nft2rftMapping;19 mapping(address => mapping(uint256 => uint256)) public nft2rftMapping;
20 mapping(address => Token) public rft2nftMapping;20 mapping(address => Token) public rft2nftMapping;
21 //use constant to reduce gas cost
21 bytes32 refungibleCollectionType = keccak256(bytes("ReFungible"));22 bytes32 constant refungibleCollectionType = keccak256(bytes("ReFungible"));
2223
23 receive() external payable onlyOwner {}24 receive() external payable onlyOwner {}
2425
51 /// Throws if `msg.sender` is not owner or admin of provided RFT collection.52 /// Throws if `msg.sender` is not owner or admin of provided RFT collection.
52 /// Can only be called by contract owner.53 /// Can only be called by contract owner.
53 /// @param _collection address of RFT collection.54 /// @param _collection address of RFT collection.
54 function setRFTCollection(address _collection) public onlyOwner {55 function setRFTCollection(address _collection) external onlyOwner {
55 require(rftCollection == address(0), "RFT collection is already set");56 require(rftCollection == address(0), "RFT collection is already set");
56 UniqueRefungible refungibleContract = UniqueRefungible(_collection);57 UniqueRefungible refungibleContract = UniqueRefungible(_collection);
57 string memory collectionType = refungibleContract.uniqueCollectionType();58 string memory collectionType = refungibleContract.uniqueCollectionType();
5859
60 // compare hashed to reduce gas cost
59 require(61 require(
60 keccak256(bytes(collectionType)) == refungibleCollectionType,62 keccak256(bytes(collectionType)) == refungibleCollectionType,
61 "Wrong collection type. Collection is not refungible."63 "Wrong collection type. Collection is not refungible."
79 string calldata _name,81 string calldata _name,
80 string calldata _description,82 string calldata _description,
81 string calldata _tokenPrefix83 string calldata _tokenPrefix
82 ) public onlyOwner {84 ) external onlyOwner {
83 require(rftCollection == address(0), "RFT collection is already set");85 require(rftCollection == address(0), "RFT collection is already set");
84 address collectionHelpers = 0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F;86 address collectionHelpers = 0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F;
85 rftCollection = CollectionHelpers(collectionHelpers).createRFTCollection(_name, _description, _tokenPrefix);87 rftCollection = CollectionHelpers(collectionHelpers).createRFTCollection(_name, _description, _tokenPrefix);
90 /// @dev Can only be called by contract owner.92 /// @dev Can only be called by contract owner.
91 /// @param collection NFT token address.93 /// @param collection NFT token address.
92 /// @param status `true` to allow and `false` to disallow NFT token.94 /// @param status `true` to allow and `false` to disallow NFT token.
93 function setNftCollectionIsAllowed(address collection, bool status) public onlyOwner {95 function setNftCollectionIsAllowed(address collection, bool status) external onlyOwner {
94 nftCollectionAllowList[collection] = status;96 nftCollectionAllowList[collection] = status;
95 emit AllowListSet(collection, status);97 emit AllowListSet(collection, status);
96 }98 }
109 address _collection,111 address _collection,
110 uint256 _token,112 uint256 _token,
111 uint128 _pieces113 uint128 _pieces
112 ) public {114 ) external {
113 require(rftCollection != address(0), "RFT collection is not set");115 require(rftCollection != address(0), "RFT collection is not set");
114 UniqueRefungible rftCollectionContract = UniqueRefungible(rftCollection);116 UniqueRefungible rftCollectionContract = UniqueRefungible(rftCollection);
115 require(117 require(
148 /// Throws if `msg.sender` isn't owner of all RFT token pieces.150 /// Throws if `msg.sender` isn't owner of all RFT token pieces.
149 /// @param _collection RFT collection address151 /// @param _collection RFT collection address
150 /// @param _token id of RFT token152 /// @param _token id of RFT token
151 function rft2nft(address _collection, uint256 _token) public {153 function rft2nft(address _collection, uint256 _token) external {
152 require(rftCollection != address(0), "RFT collection is not set");154 require(rftCollection != address(0), "RFT collection is not set");
153 require(rftCollection == _collection, "Wrong RFT collection");155 require(rftCollection == _collection, "Wrong RFT collection");
154 UniqueRefungible rftCollectionContract = UniqueRefungible(rftCollection);156 UniqueRefungible rftCollectionContract = UniqueRefungible(rftCollection);
modifiedtests/src/eth/payable.test.tsdiffbeforeafterboth
140 });140 });
141 141
142 itEth('Fee for nested calls to native methods is withdrawn from the user', async({helper}) => {142 itEth('Fee for nested calls to native methods is withdrawn from the user', async({helper}) => {
143 const CONTRACT_BALANCE = 3n * helper.balance.getOneTokenNominal();143 const CONTRACT_BALANCE = 2n * helper.balance.getOneTokenNominal();
144144
145 const deployer = await helper.eth.createAccountWithBalance(donor);145 const deployer = await helper.eth.createAccountWithBalance(donor);
146 const caller = await helper.eth.createAccountWithBalance(donor);146 const caller = await helper.eth.createAccountWithBalance(donor);
147 const contract = await deployProxyContract(helper, deployer);147 const contract = await deployProxyContract(helper, deployer);
148
149 const web3 = helper.getWeb3();
150 await web3.eth.sendTransaction({from: deployer, to: contract.options.address, value: CONTRACT_BALANCE.toString(), gas: helper.eth.DEFAULT_GAS});
151148
152 const collectionAddress = (await contract.methods.createNonfungibleCollection().send({from: caller})).events.CollectionCreated.returnValues.collection;149 const collectionAddress = (await contract.methods.createNonfungibleCollection().send({from: caller, value: Number(CONTRACT_BALANCE)})).events.CollectionCreated.returnValues.collection;
153 const initialCallerBalance = await helper.balance.getEthereum(caller);150 const initialCallerBalance = await helper.balance.getEthereum(caller);
154 const initialContractBalance = await helper.balance.getEthereum(contract.options.address);151 const initialContractBalance = await helper.balance.getEthereum(contract.options.address);
155 await contract.methods.mintNftToken(collectionAddress).send({from: caller});152 await contract.methods.mintNftToken(collectionAddress).send({from: caller});
160 });157 });
161 158
162 itEth('Fee for nested calls to create*Collection methods is withdrawn from the user and from the contract', async({helper}) => {159 itEth('Fee for nested calls to create*Collection methods is withdrawn from the user and from the contract', async({helper}) => {
163 const CONTRACT_BALANCE = 3n * helper.balance.getOneTokenNominal();160 const CONTRACT_BALANCE = 2n * helper.balance.getOneTokenNominal();
164
165 const deployer = await helper.eth.createAccountWithBalance(donor);161 const deployer = await helper.eth.createAccountWithBalance(donor);
166 const caller = await helper.eth.createAccountWithBalance(donor);162 const caller = await helper.eth.createAccountWithBalance(donor);
167 const contract = await deployProxyContract(helper, deployer);163 const contract = await deployProxyContract(helper, deployer);
168
169 const web3 = helper.getWeb3();
170 await web3.eth.sendTransaction({from: deployer, to: contract.options.address, value: CONTRACT_BALANCE.toString(), gas: helper.eth.DEFAULT_GAS});
171164
172 const initialCallerBalance = await helper.balance.getEthereum(caller);165 const initialCallerBalance = await helper.balance.getEthereum(caller);
173 const initialContractBalance = await helper.balance.getEthereum(contract.options.address);166 const initialContractBalance = await helper.balance.getEthereum(contract.options.address);
174 await contract.methods.createNonfungibleCollection().send({from: caller});167 await contract.methods.createNonfungibleCollection().send({from: caller, value: Number(CONTRACT_BALANCE)});
175 const finalCallerBalance = await helper.balance.getEthereum(caller);168 const finalCallerBalance = await helper.balance.getEthereum(caller);
176 const finalContractBalance = await helper.balance.getEthereum(contract.options.address);169 const finalContractBalance = await helper.balance.getEthereum(contract.options.address);
177 expect(finalCallerBalance < initialCallerBalance).to.be.true;170 expect(finalCallerBalance < initialCallerBalance).to.be.true;
178 expect(finalContractBalance < initialContractBalance).to.be.true;171 expect(finalContractBalance == initialContractBalance).to.be.true;
179 });172 });
180173
181 async function deployProxyContract(helper: EthUniqueHelper, deployer: string) {174 async function deployProxyContract(helper: EthUniqueHelper, deployer: string) {
182 return await helper.ethContract.deployByCode(175 return await helper.ethContract.deployByCode(
183 deployer,176 deployer,
184 'ProxyContract',177 'ProxyContract',
185 `178 `
186 // SPDX-License-Identifier: UNLICENSED179 // SPDX-License-Identifier: UNLICENSED
187 pragma solidity ^0.8.6;180 pragma solidity ^0.8.6;
188181
189 import {CollectionHelpers} from "../api/CollectionHelpers.sol";182 import {CollectionHelpers} from "../api/CollectionHelpers.sol";
190 import {UniqueNFT} from "../api/UniqueNFT.sol";183 import {UniqueNFT} from "../api/UniqueNFT.sol";
191184
192 contract ProxyContract {185 error Value(uint256 value);
186
187 contract ProxyContract {
193 bool value = false;188 bool value = false;
194 address flipper;189 address flipper;
195190
196 event CollectionCreated(address collection);191 event CollectionCreated(address collection);
197 event TokenMinted(uint256 tokenId);192 event TokenMinted(uint256 tokenId);
198193
199 receive() external payable {}194 receive() external payable {}
200195
201 constructor() {196 constructor() {
202 flipper = address(new Flipper());197 flipper = address(new Flipper());
203 }198 }
204199
205 function flip() public {200 function flip() public {
206 value = !value;201 value = !value;
207 Flipper(flipper).flip();202 Flipper(flipper).flip();
208 }203 }
209204
210 function createNonfungibleCollection() public {205 function createNonfungibleCollection() external payable {
211 address collectionHelpers = 0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F;206 address collectionHelpers = 0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F;
212 address nftCollection = CollectionHelpers(collectionHelpers).createNonfungibleCollection("A", "B", "C");207 address nftCollection = CollectionHelpers(collectionHelpers).createNonfungibleCollection{value: msg.value}("A", "B", "C");
213 emit CollectionCreated(nftCollection);208 emit CollectionCreated(nftCollection);
214 }209 }
215210
216 function mintNftToken(address collectionAddress) public {211 function mintNftToken(address collectionAddress) external {
217 UniqueNFT collection = UniqueNFT(collectionAddress);212 UniqueNFT collection = UniqueNFT(collectionAddress);
218 uint256 tokenId = collection.nextTokenId();213 uint256 tokenId = collection.nextTokenId();
219 collection.mint(msg.sender, tokenId);214 collection.mint(msg.sender, tokenId);
220 emit TokenMinted(tokenId);215 emit TokenMinted(tokenId);
221 }216 }
222217
223 function getValue() public view returns (bool) {218 function getValue() external view returns (bool) {
224 return Flipper(flipper).getValue();219 return Flipper(flipper).getValue();
225 }220 }
226 }221 }
227222
228 contract Flipper {223 contract Flipper {
229 bool value = false;224 bool value = false;
230 function flip() public {225 function flip() external {
231 value = !value;226 value = !value;
232 }227 }
233 function getValue() public view returns (bool) {228 function getValue() external view returns (bool) {
234 return value;229 return value;
235 }230 }
236 }231 }
237 `,232 `,
238 [233 [
239 {234 {
240 solPath: 'api/CollectionHelpers.sol',235 solPath: 'api/CollectionHelpers.sol',