1mod accessors;
2
3use crate::balances::credits::TokenAmount;
4use crate::data_contract::associated_token::token_configuration_convention::v0::TokenConfigurationConventionV0;
5use crate::data_contract::associated_token::token_configuration_convention::TokenConfigurationConvention;
6use crate::data_contract::associated_token::token_distribution_rules::v0::TokenDistributionRulesV0;
7use crate::data_contract::associated_token::token_distribution_rules::TokenDistributionRules;
8use crate::data_contract::associated_token::token_keeps_history_rules::v0::TokenKeepsHistoryRulesV0;
9use crate::data_contract::associated_token::token_keeps_history_rules::TokenKeepsHistoryRules;
10use crate::data_contract::associated_token::token_marketplace_rules::v0::{
11 TokenMarketplaceRulesV0, TokenTradeMode,
12};
13use crate::data_contract::associated_token::token_marketplace_rules::TokenMarketplaceRules;
14use crate::data_contract::associated_token::token_perpetual_distribution::TokenPerpetualDistribution;
15use crate::data_contract::associated_token::token_pre_programmed_distribution::TokenPreProgrammedDistribution;
16use crate::data_contract::change_control_rules::authorized_action_takers::AuthorizedActionTakers;
17use crate::data_contract::change_control_rules::v0::ChangeControlRulesV0;
18use crate::data_contract::change_control_rules::ChangeControlRules;
19use crate::data_contract::GroupContractPosition;
20#[cfg(feature = "json-conversion")]
21use crate::serialization::json_safe_fields;
22use bincode::{Decode, Encode};
23use serde::{Deserialize, Serialize};
24use std::fmt;
25
26#[cfg_attr(feature = "json-conversion", json_safe_fields)]
36#[derive(Serialize, Deserialize, Decode, Encode, Debug, Clone, PartialEq, Eq)]
37#[serde(rename_all = "camelCase")]
38pub struct TokenConfigurationV0 {
39 pub conventions: TokenConfigurationConvention,
41
42 #[serde(default = "default_change_control_rules")]
44 pub conventions_change_rules: ChangeControlRules,
45
46 #[serde(default)]
48 pub base_supply: TokenAmount,
49
50 #[serde(default)]
54 pub max_supply: Option<TokenAmount>,
55
56 #[serde(default = "default_token_keeps_history_rules")]
58 pub keeps_history: TokenKeepsHistoryRules,
59
60 #[serde(default = "default_starts_as_paused")]
64 pub start_as_paused: bool,
65
66 #[serde(default = "default_allow_transfer_to_frozen_balance")]
68 pub allow_transfer_to_frozen_balance: bool,
69
70 #[serde(default = "default_change_control_rules")]
74 pub max_supply_change_rules: ChangeControlRules,
75
76 #[serde(default = "default_token_distribution_rules")]
78 pub distribution_rules: TokenDistributionRules,
79
80 #[serde(default = "default_token_marketplace_rules")]
82 pub marketplace_rules: TokenMarketplaceRules,
83
84 #[serde(default = "default_contract_owner_change_control_rules")]
86 pub manual_minting_rules: ChangeControlRules,
87
88 #[serde(default = "default_contract_owner_change_control_rules")]
90 pub manual_burning_rules: ChangeControlRules,
91
92 #[serde(default = "default_change_control_rules")]
94 pub freeze_rules: ChangeControlRules,
95
96 #[serde(default = "default_change_control_rules")]
98 pub unfreeze_rules: ChangeControlRules,
99
100 #[serde(default = "default_change_control_rules")]
102 pub destroy_frozen_funds_rules: ChangeControlRules,
103
104 #[serde(default = "default_change_control_rules")]
106 pub emergency_action_rules: ChangeControlRules,
107
108 #[serde(default)]
110 pub main_control_group: Option<GroupContractPosition>,
111
112 #[serde(default)]
114 pub main_control_group_can_be_modified: AuthorizedActionTakers,
115
116 #[serde(default)]
118 pub description: Option<String>,
119}
120
121fn default_keeps_history() -> bool {
123 true }
125
126fn default_starts_as_paused() -> bool {
128 false
129}
130
131fn default_allow_transfer_to_frozen_balance() -> bool {
133 true
134}
135
136fn default_token_keeps_history_rules() -> TokenKeepsHistoryRules {
137 TokenKeepsHistoryRules::V0(TokenKeepsHistoryRulesV0 {
138 keeps_transfer_history: true,
139 keeps_freezing_history: true,
140 keeps_minting_history: true,
141 keeps_burning_history: true,
142 keeps_direct_pricing_history: true,
143 keeps_direct_purchase_history: true,
144 })
145}
146
147fn default_token_distribution_rules() -> TokenDistributionRules {
148 TokenDistributionRules::V0(TokenDistributionRulesV0 {
149 perpetual_distribution: None,
150 perpetual_distribution_rules: ChangeControlRules::V0(ChangeControlRulesV0 {
151 authorized_to_make_change: AuthorizedActionTakers::NoOne,
152 admin_action_takers: AuthorizedActionTakers::NoOne,
153 changing_authorized_action_takers_to_no_one_allowed: false,
154 changing_admin_action_takers_to_no_one_allowed: false,
155 self_changing_admin_action_takers_allowed: false,
156 }),
157 pre_programmed_distribution: None,
158 new_tokens_destination_identity: None,
159 new_tokens_destination_identity_rules: ChangeControlRules::V0(ChangeControlRulesV0 {
160 authorized_to_make_change: AuthorizedActionTakers::NoOne,
161 admin_action_takers: AuthorizedActionTakers::NoOne,
162 changing_authorized_action_takers_to_no_one_allowed: false,
163 changing_admin_action_takers_to_no_one_allowed: false,
164 self_changing_admin_action_takers_allowed: false,
165 }),
166 minting_allow_choosing_destination: true,
167 minting_allow_choosing_destination_rules: ChangeControlRules::V0(ChangeControlRulesV0 {
168 authorized_to_make_change: AuthorizedActionTakers::NoOne,
169 admin_action_takers: AuthorizedActionTakers::NoOne,
170 changing_authorized_action_takers_to_no_one_allowed: false,
171 changing_admin_action_takers_to_no_one_allowed: false,
172 self_changing_admin_action_takers_allowed: false,
173 }),
174 change_direct_purchase_pricing_rules: ChangeControlRules::V0(ChangeControlRulesV0 {
175 authorized_to_make_change: AuthorizedActionTakers::NoOne,
176 admin_action_takers: AuthorizedActionTakers::NoOne,
177 changing_authorized_action_takers_to_no_one_allowed: false,
178 changing_admin_action_takers_to_no_one_allowed: false,
179 self_changing_admin_action_takers_allowed: false,
180 }),
181 })
182}
183
184fn default_token_marketplace_rules() -> TokenMarketplaceRules {
185 TokenMarketplaceRules::V0(TokenMarketplaceRulesV0 {
186 trade_mode: TokenTradeMode::NotTradeable,
187 trade_mode_change_rules: ChangeControlRules::V0(ChangeControlRulesV0 {
188 authorized_to_make_change: AuthorizedActionTakers::NoOne,
189 admin_action_takers: AuthorizedActionTakers::NoOne,
190 changing_authorized_action_takers_to_no_one_allowed: false,
191 changing_admin_action_takers_to_no_one_allowed: false,
192 self_changing_admin_action_takers_allowed: false,
193 }),
194 })
195}
196
197fn default_change_control_rules() -> ChangeControlRules {
198 ChangeControlRules::V0(ChangeControlRulesV0 {
199 authorized_to_make_change: AuthorizedActionTakers::NoOne,
200 admin_action_takers: AuthorizedActionTakers::NoOne,
201 changing_authorized_action_takers_to_no_one_allowed: false,
202 changing_admin_action_takers_to_no_one_allowed: false,
203 self_changing_admin_action_takers_allowed: false,
204 })
205}
206
207fn default_contract_owner_change_control_rules() -> ChangeControlRules {
208 ChangeControlRules::V0(ChangeControlRulesV0 {
209 authorized_to_make_change: AuthorizedActionTakers::ContractOwner,
210 admin_action_takers: AuthorizedActionTakers::NoOne,
211 changing_authorized_action_takers_to_no_one_allowed: false,
212 changing_admin_action_takers_to_no_one_allowed: false,
213 self_changing_admin_action_takers_allowed: false,
214 })
215}
216
217impl fmt::Display for TokenConfigurationV0 {
218 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219 write!(
220 f,
221 "TokenConfigurationV0 {{\n conventions: {:?},\n conventions_change_rules: {:?},\n base_supply: {},\n max_supply: {:?},\n keeps_history: {},\n start_as_paused: {},\n allow_transfer_to_frozen_balance: {},\n max_supply_change_rules: {:?},\n distribution_rules: {},\n manual_minting_rules: {:?},\n manual_burning_rules: {:?},\n freeze_rules: {:?},\n unfreeze_rules: {:?},\n destroy_frozen_funds_rules: {:?},\n emergency_action_rules: {:?},\n main_control_group: {:?},\n main_control_group_can_be_modified: {:?}\n}}",
222 self.conventions,
223 self.conventions_change_rules,
224 self.base_supply,
225 self.max_supply,
226 self.keeps_history,
227 self.start_as_paused,
228 self.allow_transfer_to_frozen_balance,
229 self.max_supply_change_rules,
230 self.distribution_rules,
231 self.manual_minting_rules,
232 self.manual_burning_rules,
233 self.freeze_rules,
234 self.unfreeze_rules,
235 self.destroy_frozen_funds_rules,
236 self.emergency_action_rules,
237 self.main_control_group,
238 self.main_control_group_can_be_modified
239 )
240 }
241}
242
243#[derive(Serialize, Deserialize, Decode, Encode, Debug, Clone, Copy, PartialEq, Eq, PartialOrd)]
252pub enum TokenConfigurationPresetFeatures {
253 MostRestrictive,
258
259 WithOnlyEmergencyAction,
265
266 WithMintingAndBurningActions,
270
271 WithAllAdvancedActions,
276
277 WithExtremeActions,
284}
285
286#[derive(Serialize, Deserialize, Decode, Encode, Debug, Clone, PartialEq, Eq, PartialOrd)]
296pub struct TokenConfigurationPreset {
297 pub features: TokenConfigurationPresetFeatures,
303
304 pub action_taker: AuthorizedActionTakers,
309}
310impl TokenConfigurationPreset {
311 pub fn default_main_control_group_can_be_modified(&self) -> AuthorizedActionTakers {
312 match self.features {
313 TokenConfigurationPresetFeatures::MostRestrictive
314 | TokenConfigurationPresetFeatures::WithOnlyEmergencyAction
315 | TokenConfigurationPresetFeatures::WithMintingAndBurningActions
316 | TokenConfigurationPresetFeatures::WithAllAdvancedActions => {
317 AuthorizedActionTakers::NoOne
318 }
319 TokenConfigurationPresetFeatures::WithExtremeActions => self.action_taker,
320 }
321 }
322 pub fn default_basic_change_control_rules_v0(&self) -> ChangeControlRulesV0 {
323 match self.features {
324 TokenConfigurationPresetFeatures::MostRestrictive
325 | TokenConfigurationPresetFeatures::WithOnlyEmergencyAction => ChangeControlRulesV0 {
326 authorized_to_make_change: AuthorizedActionTakers::NoOne,
327 admin_action_takers: AuthorizedActionTakers::NoOne,
328 changing_authorized_action_takers_to_no_one_allowed: false,
329 changing_admin_action_takers_to_no_one_allowed: false,
330 self_changing_admin_action_takers_allowed: false,
331 },
332 TokenConfigurationPresetFeatures::WithMintingAndBurningActions
333 | TokenConfigurationPresetFeatures::WithAllAdvancedActions => ChangeControlRulesV0 {
334 authorized_to_make_change: self.action_taker,
335 admin_action_takers: self.action_taker,
336 changing_authorized_action_takers_to_no_one_allowed: false,
337 changing_admin_action_takers_to_no_one_allowed: false,
338 self_changing_admin_action_takers_allowed: true,
339 },
340 TokenConfigurationPresetFeatures::WithExtremeActions => ChangeControlRulesV0 {
341 authorized_to_make_change: self.action_taker,
342 admin_action_takers: self.action_taker,
343 changing_authorized_action_takers_to_no_one_allowed: true,
344 changing_admin_action_takers_to_no_one_allowed: true,
345 self_changing_admin_action_takers_allowed: true,
346 },
347 }
348 }
349
350 pub fn default_advanced_change_control_rules_v0(&self) -> ChangeControlRulesV0 {
351 match self.features {
352 TokenConfigurationPresetFeatures::MostRestrictive
353 | TokenConfigurationPresetFeatures::WithOnlyEmergencyAction
354 | TokenConfigurationPresetFeatures::WithMintingAndBurningActions => {
355 ChangeControlRulesV0 {
356 authorized_to_make_change: AuthorizedActionTakers::NoOne,
357 admin_action_takers: AuthorizedActionTakers::NoOne,
358 changing_authorized_action_takers_to_no_one_allowed: false,
359 changing_admin_action_takers_to_no_one_allowed: false,
360 self_changing_admin_action_takers_allowed: false,
361 }
362 }
363 TokenConfigurationPresetFeatures::WithAllAdvancedActions => ChangeControlRulesV0 {
364 authorized_to_make_change: self.action_taker,
365 admin_action_takers: self.action_taker,
366 changing_authorized_action_takers_to_no_one_allowed: false,
367 changing_admin_action_takers_to_no_one_allowed: false,
368 self_changing_admin_action_takers_allowed: true,
369 },
370 TokenConfigurationPresetFeatures::WithExtremeActions => ChangeControlRulesV0 {
371 authorized_to_make_change: self.action_taker,
372 admin_action_takers: self.action_taker,
373 changing_authorized_action_takers_to_no_one_allowed: true,
374 changing_admin_action_takers_to_no_one_allowed: true,
375 self_changing_admin_action_takers_allowed: true,
376 },
377 }
378 }
379
380 pub fn default_emergency_action_change_control_rules_v0(&self) -> ChangeControlRulesV0 {
381 match self.features {
382 TokenConfigurationPresetFeatures::MostRestrictive => ChangeControlRulesV0 {
383 authorized_to_make_change: AuthorizedActionTakers::NoOne,
384 admin_action_takers: AuthorizedActionTakers::NoOne,
385 changing_authorized_action_takers_to_no_one_allowed: false,
386 changing_admin_action_takers_to_no_one_allowed: false,
387 self_changing_admin_action_takers_allowed: false,
388 },
389 TokenConfigurationPresetFeatures::WithAllAdvancedActions
390 | TokenConfigurationPresetFeatures::WithMintingAndBurningActions
391 | TokenConfigurationPresetFeatures::WithOnlyEmergencyAction => ChangeControlRulesV0 {
392 authorized_to_make_change: self.action_taker,
393 admin_action_takers: self.action_taker,
394 changing_authorized_action_takers_to_no_one_allowed: false,
395 changing_admin_action_takers_to_no_one_allowed: false,
396 self_changing_admin_action_takers_allowed: true,
397 },
398 TokenConfigurationPresetFeatures::WithExtremeActions => ChangeControlRulesV0 {
399 authorized_to_make_change: self.action_taker,
400 admin_action_takers: self.action_taker,
401 changing_authorized_action_takers_to_no_one_allowed: true,
402 changing_admin_action_takers_to_no_one_allowed: true,
403 self_changing_admin_action_takers_allowed: true,
404 },
405 }
406 }
407
408 pub fn default_distribution_rules_v0(
409 &self,
410 perpetual_distribution: Option<TokenPerpetualDistribution>,
411 pre_programmed_distribution: Option<TokenPreProgrammedDistribution>,
412 with_direct_pricing: bool,
413 ) -> TokenDistributionRulesV0 {
414 TokenDistributionRulesV0 {
415 perpetual_distribution,
416 perpetual_distribution_rules: self.default_advanced_change_control_rules_v0().into(),
417 pre_programmed_distribution,
418 new_tokens_destination_identity: None,
419 new_tokens_destination_identity_rules: self
420 .default_basic_change_control_rules_v0()
421 .into(),
422 minting_allow_choosing_destination: true,
423 minting_allow_choosing_destination_rules: self
424 .default_basic_change_control_rules_v0()
425 .into(),
426 change_direct_purchase_pricing_rules: if with_direct_pricing {
427 self.default_basic_change_control_rules_v0().into()
428 } else {
429 ChangeControlRulesV0 {
430 authorized_to_make_change: AuthorizedActionTakers::NoOne,
431 admin_action_takers: AuthorizedActionTakers::NoOne,
432 changing_authorized_action_takers_to_no_one_allowed: false,
433 changing_admin_action_takers_to_no_one_allowed: false,
434 self_changing_admin_action_takers_allowed: false,
435 }
436 .into()
437 },
438 }
439 }
440
441 pub fn default_marketplace_rules_v0(&self) -> TokenMarketplaceRulesV0 {
442 TokenMarketplaceRulesV0 {
443 trade_mode: TokenTradeMode::NotTradeable,
444 trade_mode_change_rules: self.default_basic_change_control_rules_v0().into(),
445 }
446 }
447
448 pub fn token_configuration_v0(
449 &self,
450 conventions: TokenConfigurationConvention,
451 base_supply: TokenAmount,
452 max_supply: Option<TokenAmount>,
453 keeps_all_history: bool,
454 with_direct_pricing: bool,
455 ) -> TokenConfigurationV0 {
456 TokenConfigurationV0 {
457 conventions,
458 conventions_change_rules: self.default_basic_change_control_rules_v0().into(),
459 base_supply,
460 max_supply,
461 keeps_history: TokenKeepsHistoryRulesV0::default_for_keeping_all_history(
462 keeps_all_history,
463 )
464 .into(),
465 start_as_paused: false,
466 allow_transfer_to_frozen_balance: true,
467 max_supply_change_rules: self.default_advanced_change_control_rules_v0().into(),
468 distribution_rules: self
469 .default_distribution_rules_v0(None, None, with_direct_pricing)
470 .into(),
471 marketplace_rules: self.default_marketplace_rules_v0().into(),
472 manual_minting_rules: self.default_basic_change_control_rules_v0().into(),
473 manual_burning_rules: self.default_basic_change_control_rules_v0().into(),
474 freeze_rules: self.default_advanced_change_control_rules_v0().into(),
475 unfreeze_rules: self.default_advanced_change_control_rules_v0().into(),
476 destroy_frozen_funds_rules: self.default_advanced_change_control_rules_v0().into(),
477 emergency_action_rules: self
478 .default_emergency_action_change_control_rules_v0()
479 .into(),
480 main_control_group: None,
481 main_control_group_can_be_modified: self.default_main_control_group_can_be_modified(),
482 description: None,
483 }
484 }
485}
486
487impl TokenConfigurationV0 {
488 pub fn default_most_restrictive() -> Self {
489 TokenConfigurationPreset {
490 features: TokenConfigurationPresetFeatures::MostRestrictive,
491 action_taker: AuthorizedActionTakers::NoOne,
492 }
493 .token_configuration_v0(
494 TokenConfigurationConvention::V0(TokenConfigurationConventionV0 {
495 localizations: Default::default(),
496 decimals: 8,
497 }),
498 100000,
499 None,
500 true,
501 false,
502 )
503 }
504
505 pub fn with_base_supply(mut self, base_supply: TokenAmount) -> Self {
506 self.base_supply = base_supply;
507 self
508 }
509}
510
511#[cfg(test)]
512mod tests {
513 use super::*;
514 use crate::data_contract::associated_token::token_configuration::accessors::v0::{
515 TokenConfigurationV0Getters, TokenConfigurationV0Setters,
516 };
517 use platform_value::Identifier;
518
519 fn preset(
520 features: TokenConfigurationPresetFeatures,
521 action_taker: AuthorizedActionTakers,
522 ) -> TokenConfigurationPreset {
523 TokenConfigurationPreset {
524 features,
525 action_taker,
526 }
527 }
528
529 #[test]
532 fn preset_main_control_group_can_be_modified_most_restrictive_is_no_one() {
533 let p = preset(
534 TokenConfigurationPresetFeatures::MostRestrictive,
535 AuthorizedActionTakers::ContractOwner,
536 );
537 assert_eq!(
538 p.default_main_control_group_can_be_modified(),
539 AuthorizedActionTakers::NoOne
540 );
541 }
542
543 #[test]
544 fn preset_main_control_group_can_be_modified_only_emergency_is_no_one() {
545 let p = preset(
546 TokenConfigurationPresetFeatures::WithOnlyEmergencyAction,
547 AuthorizedActionTakers::ContractOwner,
548 );
549 assert_eq!(
550 p.default_main_control_group_can_be_modified(),
551 AuthorizedActionTakers::NoOne
552 );
553 }
554
555 #[test]
556 fn preset_main_control_group_can_be_modified_minting_burning_is_no_one() {
557 let p = preset(
558 TokenConfigurationPresetFeatures::WithMintingAndBurningActions,
559 AuthorizedActionTakers::ContractOwner,
560 );
561 assert_eq!(
562 p.default_main_control_group_can_be_modified(),
563 AuthorizedActionTakers::NoOne
564 );
565 }
566
567 #[test]
568 fn preset_main_control_group_can_be_modified_advanced_is_no_one() {
569 let p = preset(
570 TokenConfigurationPresetFeatures::WithAllAdvancedActions,
571 AuthorizedActionTakers::ContractOwner,
572 );
573 assert_eq!(
574 p.default_main_control_group_can_be_modified(),
575 AuthorizedActionTakers::NoOne
576 );
577 }
578
579 #[test]
580 fn preset_main_control_group_can_be_modified_extreme_is_action_taker() {
581 let taker = AuthorizedActionTakers::Identity(Identifier::from([9u8; 32]));
582 let p = preset(TokenConfigurationPresetFeatures::WithExtremeActions, taker);
583 assert_eq!(p.default_main_control_group_can_be_modified(), taker);
584 }
585
586 #[test]
589 fn preset_basic_rules_most_restrictive_is_no_one_locked() {
590 let p = preset(
591 TokenConfigurationPresetFeatures::MostRestrictive,
592 AuthorizedActionTakers::ContractOwner,
593 );
594 let rules = p.default_basic_change_control_rules_v0();
595 assert_eq!(
596 rules.authorized_to_make_change,
597 AuthorizedActionTakers::NoOne
598 );
599 assert_eq!(rules.admin_action_takers, AuthorizedActionTakers::NoOne);
600 assert!(!rules.changing_authorized_action_takers_to_no_one_allowed);
601 assert!(!rules.changing_admin_action_takers_to_no_one_allowed);
602 assert!(!rules.self_changing_admin_action_takers_allowed);
603 }
604
605 #[test]
606 fn preset_basic_rules_only_emergency_is_no_one_locked() {
607 let p = preset(
608 TokenConfigurationPresetFeatures::WithOnlyEmergencyAction,
609 AuthorizedActionTakers::ContractOwner,
610 );
611 let rules = p.default_basic_change_control_rules_v0();
612 assert_eq!(
613 rules.authorized_to_make_change,
614 AuthorizedActionTakers::NoOne
615 );
616 }
617
618 #[test]
619 fn preset_basic_rules_minting_burning_is_action_taker_self_mutable() {
620 let taker = AuthorizedActionTakers::ContractOwner;
621 let p = preset(
622 TokenConfigurationPresetFeatures::WithMintingAndBurningActions,
623 taker,
624 );
625 let rules = p.default_basic_change_control_rules_v0();
626 assert_eq!(rules.authorized_to_make_change, taker);
627 assert_eq!(rules.admin_action_takers, taker);
628 assert!(rules.self_changing_admin_action_takers_allowed);
629 assert!(!rules.changing_authorized_action_takers_to_no_one_allowed);
631 }
632
633 #[test]
634 fn preset_basic_rules_advanced_is_action_taker_self_mutable() {
635 let taker = AuthorizedActionTakers::ContractOwner;
636 let p = preset(
637 TokenConfigurationPresetFeatures::WithAllAdvancedActions,
638 taker,
639 );
640 let rules = p.default_basic_change_control_rules_v0();
641 assert_eq!(rules.authorized_to_make_change, taker);
642 assert!(rules.self_changing_admin_action_takers_allowed);
643 assert!(!rules.changing_admin_action_takers_to_no_one_allowed);
644 }
645
646 #[test]
647 fn preset_basic_rules_extreme_allows_no_one_transitions() {
648 let taker = AuthorizedActionTakers::ContractOwner;
649 let p = preset(TokenConfigurationPresetFeatures::WithExtremeActions, taker);
650 let rules = p.default_basic_change_control_rules_v0();
651 assert_eq!(rules.authorized_to_make_change, taker);
652 assert!(rules.changing_authorized_action_takers_to_no_one_allowed);
653 assert!(rules.changing_admin_action_takers_to_no_one_allowed);
654 assert!(rules.self_changing_admin_action_takers_allowed);
655 }
656
657 #[test]
660 fn preset_advanced_rules_most_restrictive_is_locked() {
661 let p = preset(
662 TokenConfigurationPresetFeatures::MostRestrictive,
663 AuthorizedActionTakers::ContractOwner,
664 );
665 let rules = p.default_advanced_change_control_rules_v0();
666 assert_eq!(
667 rules.authorized_to_make_change,
668 AuthorizedActionTakers::NoOne
669 );
670 assert!(!rules.self_changing_admin_action_takers_allowed);
671 }
672
673 #[test]
674 fn preset_advanced_rules_minting_burning_is_locked() {
675 let p = preset(
676 TokenConfigurationPresetFeatures::WithMintingAndBurningActions,
677 AuthorizedActionTakers::ContractOwner,
678 );
679 let rules = p.default_advanced_change_control_rules_v0();
681 assert_eq!(
682 rules.authorized_to_make_change,
683 AuthorizedActionTakers::NoOne
684 );
685 assert_eq!(rules.admin_action_takers, AuthorizedActionTakers::NoOne);
686 }
687
688 #[test]
689 fn preset_advanced_rules_only_emergency_is_locked() {
690 let p = preset(
691 TokenConfigurationPresetFeatures::WithOnlyEmergencyAction,
692 AuthorizedActionTakers::ContractOwner,
693 );
694 let rules = p.default_advanced_change_control_rules_v0();
695 assert_eq!(
696 rules.authorized_to_make_change,
697 AuthorizedActionTakers::NoOne
698 );
699 }
700
701 #[test]
702 fn preset_advanced_rules_advanced_allows_action_taker() {
703 let taker = AuthorizedActionTakers::ContractOwner;
704 let p = preset(
705 TokenConfigurationPresetFeatures::WithAllAdvancedActions,
706 taker,
707 );
708 let rules = p.default_advanced_change_control_rules_v0();
709 assert_eq!(rules.authorized_to_make_change, taker);
710 assert!(rules.self_changing_admin_action_takers_allowed);
711 assert!(!rules.changing_authorized_action_takers_to_no_one_allowed);
712 }
713
714 #[test]
715 fn preset_advanced_rules_extreme_allows_everything() {
716 let taker = AuthorizedActionTakers::ContractOwner;
717 let p = preset(TokenConfigurationPresetFeatures::WithExtremeActions, taker);
718 let rules = p.default_advanced_change_control_rules_v0();
719 assert!(rules.changing_authorized_action_takers_to_no_one_allowed);
720 assert!(rules.changing_admin_action_takers_to_no_one_allowed);
721 assert!(rules.self_changing_admin_action_takers_allowed);
722 }
723
724 #[test]
727 fn preset_emergency_rules_most_restrictive_is_no_one() {
728 let p = preset(
729 TokenConfigurationPresetFeatures::MostRestrictive,
730 AuthorizedActionTakers::ContractOwner,
731 );
732 let rules = p.default_emergency_action_change_control_rules_v0();
733 assert_eq!(
734 rules.authorized_to_make_change,
735 AuthorizedActionTakers::NoOne
736 );
737 }
738
739 #[test]
740 fn preset_emergency_rules_only_emergency_allows_action_taker() {
741 let taker = AuthorizedActionTakers::ContractOwner;
742 let p = preset(
743 TokenConfigurationPresetFeatures::WithOnlyEmergencyAction,
744 taker,
745 );
746 let rules = p.default_emergency_action_change_control_rules_v0();
747 assert_eq!(rules.authorized_to_make_change, taker);
748 assert!(rules.self_changing_admin_action_takers_allowed);
749 }
750
751 #[test]
752 fn preset_emergency_rules_minting_burning_allows_action_taker() {
753 let taker = AuthorizedActionTakers::ContractOwner;
754 let p = preset(
755 TokenConfigurationPresetFeatures::WithMintingAndBurningActions,
756 taker,
757 );
758 let rules = p.default_emergency_action_change_control_rules_v0();
759 assert_eq!(rules.authorized_to_make_change, taker);
760 assert!(rules.self_changing_admin_action_takers_allowed);
761 }
762
763 #[test]
764 fn preset_emergency_rules_advanced_allows_action_taker() {
765 let taker = AuthorizedActionTakers::ContractOwner;
766 let p = preset(
767 TokenConfigurationPresetFeatures::WithAllAdvancedActions,
768 taker,
769 );
770 let rules = p.default_emergency_action_change_control_rules_v0();
771 assert_eq!(rules.authorized_to_make_change, taker);
772 }
773
774 #[test]
775 fn preset_emergency_rules_extreme_allows_no_one_transitions() {
776 let taker = AuthorizedActionTakers::ContractOwner;
777 let p = preset(TokenConfigurationPresetFeatures::WithExtremeActions, taker);
778 let rules = p.default_emergency_action_change_control_rules_v0();
779 assert!(rules.changing_authorized_action_takers_to_no_one_allowed);
780 }
781
782 #[test]
785 fn preset_distribution_rules_with_direct_pricing_uses_basic_rules() {
786 let taker = AuthorizedActionTakers::ContractOwner;
787 let p = preset(TokenConfigurationPresetFeatures::WithExtremeActions, taker);
788 let rules = p.default_distribution_rules_v0(None, None, true);
789 assert_eq!(
791 rules
792 .change_direct_purchase_pricing_rules
793 .authorized_to_make_change_action_takers(),
794 &taker
795 );
796 }
797
798 #[test]
799 fn preset_distribution_rules_without_direct_pricing_locks_it_down() {
800 let taker = AuthorizedActionTakers::ContractOwner;
801 let p = preset(TokenConfigurationPresetFeatures::WithExtremeActions, taker);
802 let rules = p.default_distribution_rules_v0(None, None, false);
803 assert_eq!(
805 rules
806 .change_direct_purchase_pricing_rules
807 .authorized_to_make_change_action_takers(),
808 &AuthorizedActionTakers::NoOne
809 );
810 }
811
812 #[test]
813 fn preset_distribution_rules_minting_choosing_destination_defaults_true() {
814 let p = preset(
815 TokenConfigurationPresetFeatures::MostRestrictive,
816 AuthorizedActionTakers::NoOne,
817 );
818 let rules = p.default_distribution_rules_v0(None, None, false);
819 assert!(rules.minting_allow_choosing_destination);
820 assert!(rules.new_tokens_destination_identity.is_none());
821 assert!(rules.perpetual_distribution.is_none());
822 assert!(rules.pre_programmed_distribution.is_none());
823 }
824
825 #[test]
828 fn preset_marketplace_rules_default_is_not_tradeable() {
829 let p = preset(
830 TokenConfigurationPresetFeatures::MostRestrictive,
831 AuthorizedActionTakers::NoOne,
832 );
833 let mp = p.default_marketplace_rules_v0();
834 assert_eq!(mp.trade_mode, TokenTradeMode::NotTradeable);
835 }
836
837 #[test]
840 fn preset_token_configuration_v0_populates_fields() {
841 let taker = AuthorizedActionTakers::ContractOwner;
842 let p = preset(TokenConfigurationPresetFeatures::WithExtremeActions, taker);
843 let conventions = TokenConfigurationConvention::V0(TokenConfigurationConventionV0 {
844 localizations: Default::default(),
845 decimals: 4,
846 });
847 let config = p.token_configuration_v0(conventions, 1_000, Some(5_000), true, true);
848 assert_eq!(config.base_supply, 1_000);
849 assert_eq!(config.max_supply, Some(5_000));
850 assert_eq!(
851 config
852 .manual_minting_rules
853 .authorized_to_make_change_action_takers(),
854 &taker
855 );
856 assert!(!config.start_as_paused);
858 assert!(config.allow_transfer_to_frozen_balance);
859 assert_eq!(config.main_control_group, None);
860 assert_eq!(config.main_control_group_can_be_modified, taker);
862 assert!(config.description.is_none());
864 }
865
866 #[test]
867 fn preset_token_configuration_keeps_all_history_true() {
868 let p = preset(
869 TokenConfigurationPresetFeatures::MostRestrictive,
870 AuthorizedActionTakers::NoOne,
871 );
872 let conventions = TokenConfigurationConvention::V0(TokenConfigurationConventionV0 {
873 localizations: Default::default(),
874 decimals: 8,
875 });
876 let cfg = p.token_configuration_v0(conventions, 100, None, true, false);
877 match &cfg.keeps_history {
879 TokenKeepsHistoryRules::V0(v0) => {
880 assert!(v0.keeps_transfer_history);
881 assert!(v0.keeps_freezing_history);
882 assert!(v0.keeps_minting_history);
883 assert!(v0.keeps_burning_history);
884 assert!(v0.keeps_direct_pricing_history);
885 assert!(v0.keeps_direct_purchase_history);
886 }
887 }
888 }
889
890 #[test]
891 fn preset_token_configuration_keeps_all_history_false() {
892 let p = preset(
893 TokenConfigurationPresetFeatures::MostRestrictive,
894 AuthorizedActionTakers::NoOne,
895 );
896 let conventions = TokenConfigurationConvention::V0(TokenConfigurationConventionV0 {
897 localizations: Default::default(),
898 decimals: 8,
899 });
900 let cfg = p.token_configuration_v0(conventions, 100, None, false, false);
901 match &cfg.keeps_history {
902 TokenKeepsHistoryRules::V0(v0) => {
903 assert!(!v0.keeps_transfer_history);
904 assert!(!v0.keeps_direct_purchase_history);
905 }
906 }
907 }
908
909 #[test]
912 fn token_configuration_v0_default_most_restrictive_has_no_max_supply() {
913 let c = TokenConfigurationV0::default_most_restrictive();
914 assert_eq!(c.base_supply, 100_000);
915 assert!(c.max_supply.is_none());
916 assert_eq!(
917 c.main_control_group_can_be_modified,
918 AuthorizedActionTakers::NoOne
919 );
920 }
921
922 #[test]
923 fn token_configuration_v0_with_base_supply_overrides_value() {
924 let c = TokenConfigurationV0::default_most_restrictive().with_base_supply(42);
925 assert_eq!(c.base_supply, 42);
926 }
927
928 #[test]
931 fn display_token_configuration_v0_contains_key_fields() {
932 let c = TokenConfigurationV0::default_most_restrictive();
933 let s = format!("{}", c);
934 assert!(s.contains("TokenConfigurationV0"));
935 assert!(s.contains("base_supply"));
936 assert!(s.contains("main_control_group"));
937 }
938
939 #[test]
942 fn all_used_group_positions_empty_when_no_groups_referenced() {
943 let c = TokenConfigurationV0::default_most_restrictive();
944 let (positions, uses_main) = c.all_used_group_positions();
945 assert!(positions.is_empty());
946 assert!(!uses_main);
947 }
948
949 #[test]
950 fn all_used_group_positions_collects_from_group_variant_in_rules() {
951 let mut c = TokenConfigurationV0::default_most_restrictive();
952 c.freeze_rules = ChangeControlRules::V0(ChangeControlRulesV0 {
953 authorized_to_make_change: AuthorizedActionTakers::Group(7),
954 admin_action_takers: AuthorizedActionTakers::Group(9),
955 changing_authorized_action_takers_to_no_one_allowed: false,
956 changing_admin_action_takers_to_no_one_allowed: false,
957 self_changing_admin_action_takers_allowed: false,
958 });
959 let (positions, uses_main) = c.all_used_group_positions();
960 assert!(positions.contains(&7));
961 assert!(positions.contains(&9));
962 assert!(!uses_main);
963 }
964
965 #[test]
966 fn all_used_group_positions_flags_main_group_usage() {
967 let mut c = TokenConfigurationV0::default_most_restrictive();
968 c.emergency_action_rules = ChangeControlRules::V0(ChangeControlRulesV0 {
969 authorized_to_make_change: AuthorizedActionTakers::MainGroup,
970 admin_action_takers: AuthorizedActionTakers::NoOne,
971 changing_authorized_action_takers_to_no_one_allowed: false,
972 changing_admin_action_takers_to_no_one_allowed: false,
973 self_changing_admin_action_takers_allowed: false,
974 });
975 let (_, uses_main) = c.all_used_group_positions();
976 assert!(uses_main);
977 }
978
979 #[test]
980 fn all_used_group_positions_includes_main_control_group() {
981 let mut c = TokenConfigurationV0::default_most_restrictive();
982 c.main_control_group = Some(42);
983 let (positions, _) = c.all_used_group_positions();
984 assert!(positions.contains(&42));
985 }
986
987 #[test]
988 fn all_used_group_positions_includes_positions_from_main_control_group_can_be_modified() {
989 let mut c = TokenConfigurationV0::default_most_restrictive();
990 c.main_control_group_can_be_modified = AuthorizedActionTakers::Group(11);
991 let (positions, _) = c.all_used_group_positions();
992 assert!(positions.contains(&11));
993 }
994
995 #[test]
996 fn all_used_group_positions_ignores_contract_owner_and_identity_and_no_one() {
997 let mut c = TokenConfigurationV0::default_most_restrictive();
998 c.manual_minting_rules = ChangeControlRules::V0(ChangeControlRulesV0 {
999 authorized_to_make_change: AuthorizedActionTakers::ContractOwner,
1000 admin_action_takers: AuthorizedActionTakers::Identity(Identifier::from([1u8; 32])),
1001 changing_authorized_action_takers_to_no_one_allowed: false,
1002 changing_admin_action_takers_to_no_one_allowed: false,
1003 self_changing_admin_action_takers_allowed: false,
1004 });
1005 let (positions, uses_main) = c.all_used_group_positions();
1006 assert!(positions.is_empty());
1007 assert!(!uses_main);
1008 }
1009
1010 #[test]
1013 fn all_change_control_rules_returns_expected_rule_names() {
1014 let c = TokenConfigurationV0::default_most_restrictive();
1015 let rules = c.all_change_control_rules();
1016 let names: Vec<&str> = rules.iter().map(|(name, _)| *name).collect();
1017 assert!(names.contains(&"max_supply_change_rules"));
1018 assert!(names.contains(&"conventions_change_rules"));
1019 assert!(names.contains(&"manual_minting_rules"));
1020 assert!(names.contains(&"manual_burning_rules"));
1021 assert!(names.contains(&"freeze_rules"));
1022 assert!(names.contains(&"unfreeze_rules"));
1023 assert!(names.contains(&"destroy_frozen_funds_rules"));
1024 assert!(names.contains(&"emergency_action_rules"));
1025 assert!(names.contains(&"trade_mode_change_rules"));
1026 assert_eq!(rules.len(), 13);
1028 }
1029
1030 #[test]
1033 fn setters_set_description_max_supply_base_supply_main_control_group() {
1034 let mut c = TokenConfigurationV0::default_most_restrictive();
1035 c.set_description(Some("my token".to_string()));
1036 c.set_max_supply(Some(999));
1037 c.set_base_supply(77);
1038 c.set_main_control_group(Some(3));
1039 c.set_start_as_paused(true);
1040 c.allow_transfer_to_frozen_balance(false);
1041 c.set_main_control_group_can_be_modified(AuthorizedActionTakers::ContractOwner);
1042 assert_eq!(c.description(), &Some("my token".to_string()));
1043 assert_eq!(c.max_supply(), Some(999));
1044 assert_eq!(c.base_supply(), 77);
1045 assert_eq!(c.main_control_group(), Some(3));
1046 assert!(c.start_as_paused());
1047 assert!(!c.is_allowed_transfer_to_frozen_balance());
1048 assert_eq!(
1049 c.main_control_group_can_be_modified(),
1050 &AuthorizedActionTakers::ContractOwner
1051 );
1052 }
1053}