Skip to main content

dpp/data_contract/associated_token/token_configuration/v0/
mod.rs

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/// Defines the complete configuration for a version 0 token contract.
27///
28/// `TokenConfigurationV0` encapsulates all metadata, control rules, supply settings,
29/// and governance constraints used to initialize and manage a token instance on Platform.
30/// This structure serves as the core representation of a token's logic, permissions,
31/// and capabilities.
32///
33/// This configuration is designed to be deterministic and versioned for compatibility
34/// across protocol upgrades and validation environments.
35#[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    /// Metadata conventions, including decimals and localizations.
40    pub conventions: TokenConfigurationConvention,
41
42    /// Change control rules governing who can modify the conventions field.
43    #[serde(default = "default_change_control_rules")]
44    pub conventions_change_rules: ChangeControlRules,
45
46    /// The initial token supply minted at creation.
47    #[serde(default)]
48    pub base_supply: TokenAmount,
49
50    /// The maximum allowable supply of the token.
51    ///
52    /// If `None`, the supply is unbounded unless otherwise constrained by minting logic.
53    #[serde(default)]
54    pub max_supply: Option<TokenAmount>,
55
56    /// Configuration governing which historical actions are recorded for this token.
57    #[serde(default = "default_token_keeps_history_rules")]
58    pub keeps_history: TokenKeepsHistoryRules,
59
60    /// Indicates whether the token should start in a paused state.
61    ///
62    /// When `true`, transfers are disallowed until explicitly unpaused via an emergency action.
63    #[serde(default = "default_starts_as_paused")]
64    pub start_as_paused: bool,
65
66    /// Allows minting and transferring to frozen token balances if enabled.
67    #[serde(default = "default_allow_transfer_to_frozen_balance")]
68    pub allow_transfer_to_frozen_balance: bool,
69
70    /// Change control rules for updating the `max_supply`.
71    ///
72    /// Note: The `max_supply` can never be reduced below the `base_supply`.
73    #[serde(default = "default_change_control_rules")]
74    pub max_supply_change_rules: ChangeControlRules,
75
76    /// Defines the token's distribution logic, including perpetual and pre-programmed distributions.
77    #[serde(default = "default_token_distribution_rules")]
78    pub distribution_rules: TokenDistributionRules,
79
80    /// Defines the token's marketplace logic.
81    #[serde(default = "default_token_marketplace_rules")]
82    pub marketplace_rules: TokenMarketplaceRules,
83
84    /// Rules controlling who is authorized to perform manual minting of tokens.
85    #[serde(default = "default_contract_owner_change_control_rules")]
86    pub manual_minting_rules: ChangeControlRules,
87
88    /// Rules controlling who is authorized to perform manual burning of tokens.
89    #[serde(default = "default_contract_owner_change_control_rules")]
90    pub manual_burning_rules: ChangeControlRules,
91
92    /// Rules governing who may freeze token balances.
93    #[serde(default = "default_change_control_rules")]
94    pub freeze_rules: ChangeControlRules,
95
96    /// Rules governing who may unfreeze token balances.
97    #[serde(default = "default_change_control_rules")]
98    pub unfreeze_rules: ChangeControlRules,
99
100    /// Rules governing who may destroy frozen funds.
101    #[serde(default = "default_change_control_rules")]
102    pub destroy_frozen_funds_rules: ChangeControlRules,
103
104    /// Rules governing who may invoke emergency actions, such as pausing transfers.
105    #[serde(default = "default_change_control_rules")]
106    pub emergency_action_rules: ChangeControlRules,
107
108    /// Optional reference to the group assigned as the token's main control group.
109    #[serde(default)]
110    pub main_control_group: Option<GroupContractPosition>,
111
112    /// Defines whether and how the main control group assignment may be modified.
113    #[serde(default)]
114    pub main_control_group_can_be_modified: AuthorizedActionTakers,
115
116    /// Optional textual description of the token's purpose, behavior, or metadata.
117    #[serde(default)]
118    pub description: Option<String>,
119}
120
121// Default function for `keeps_history`
122fn default_keeps_history() -> bool {
123    true // Default to `true` for keeps_history
124}
125
126// Default function for `starts_as_paused`
127fn default_starts_as_paused() -> bool {
128    false
129}
130
131// Default function for `allow_transfer_to_frozen_balance`
132fn 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/// Represents predefined capability levels for token control presets.
244///
245/// `TokenConfigurationPresetFeatures` defines a hierarchy of governance capabilities
246/// that can be used to initialize rule sets for a token. Each variant enables a specific
247/// scope of permitted actions, allowing for simple selection of common governance models.
248///
249/// These presets are intended to be used in conjunction with `TokenConfigurationPreset`
250/// to simplify token setup and enforce governance constraints consistently.
251#[derive(Serialize, Deserialize, Decode, Encode, Debug, Clone, Copy, PartialEq, Eq, PartialOrd)]
252pub enum TokenConfigurationPresetFeatures {
253    /// No actions are permitted after initialization. All governance and control
254    /// settings are immutable.
255    ///
256    /// Suitable for tokens that should remain fixed and tamper-proof.
257    MostRestrictive,
258
259    /// Only emergency actions (e.g., pausing the token) are permitted.
260    ///
261    /// Minting, burning, and advanced operations (such as freezing) are disallowed.
262    /// This preset allows minimal control for critical situations without risking
263    /// token supply or ownership manipulation.
264    WithOnlyEmergencyAction,
265
266    /// Allows minting and burning operations, but not advanced features such as freezing.
267    ///
268    /// Enables supply management without enabling full administrative capabilities.
269    WithMintingAndBurningActions,
270
271    /// Grants the ability to perform advanced actions, including freezing and unfreezing balances.
272    ///
273    /// Minting and burning are also permitted. Suitable for tokens that require
274    /// moderate administrative control without total override capabilities.
275    WithAllAdvancedActions,
276
277    /// The action taker is a god, he can do everything, even taking away his own power.
278    /// This grants unrestricted control to the action taker, including the ability to revoke
279    /// their own permissions or transfer all governance.
280    ///
281    /// This includes minting, burning, freezing, emergency actions, and full rule modification.
282    /// Should only be used with trusted or self-destructible authorities.
283    WithExtremeActions,
284}
285
286/// A high-level preset representing common configurations for token governance and control.
287///
288/// `TokenConfigurationPreset` provides a simplified way to initialize a set of
289/// predefined token rules (e.g., minting, burning, freezing, emergency actions)
290/// by selecting a feature set (`features`) and defining the authorized actor (`action_taker`)
291/// responsible for performing allowed actions.
292///
293/// This abstraction allows users to choose between common control configurations
294/// ranging from immutable tokens to fully administrator-controlled assets.
295#[derive(Serialize, Deserialize, Decode, Encode, Debug, Clone, PartialEq, Eq, PartialOrd)]
296#[serde(rename_all = "camelCase")]
297pub struct TokenConfigurationPreset {
298    /// Defines the set of capabilities enabled in this preset (e.g., whether minting,
299    /// burning, freezing, or emergency actions are permitted).
300    ///
301    /// The selected feature set determines the default rule behavior for all change control
302    /// and governance actions within the token configuration.
303    pub features: TokenConfigurationPresetFeatures,
304
305    /// The identity or group authorized to perform actions defined by the preset.
306    ///
307    /// This includes acting as the admin for various rule changes, executing allowed token
308    /// operations, or performing emergency control (depending on the selected feature set).
309    pub action_taker: AuthorizedActionTakers,
310}
311
312// Manual impls because the preset types are flat (not versioned V0/V1).
313#[cfg(all(feature = "json-conversion", feature = "serde-conversion"))]
314impl crate::serialization::JsonConvertible for TokenConfigurationPresetFeatures {}
315
316#[cfg(all(feature = "value-conversion", feature = "serde-conversion"))]
317impl crate::serialization::ValueConvertible for TokenConfigurationPresetFeatures {}
318
319#[cfg(all(feature = "json-conversion", feature = "serde-conversion"))]
320impl crate::serialization::JsonConvertible for TokenConfigurationPreset {}
321
322#[cfg(all(feature = "value-conversion", feature = "serde-conversion"))]
323impl crate::serialization::ValueConvertible for TokenConfigurationPreset {}
324
325#[cfg(all(
326    test,
327    feature = "json-conversion",
328    feature = "value-conversion",
329    feature = "serde-conversion"
330))]
331mod json_convertible_tests_preset {
332    use super::*;
333    use crate::serialization::{JsonConvertible, ValueConvertible};
334    use platform_value::platform_value;
335    use serde_json::json;
336
337    fn fixture() -> TokenConfigurationPreset {
338        TokenConfigurationPreset {
339            features: TokenConfigurationPresetFeatures::WithAllAdvancedActions,
340            action_taker: AuthorizedActionTakers::Group(7),
341        }
342    }
343
344    #[test]
345    fn preset_json_round_trip_with_full_wire_shape() {
346        let original = fixture();
347        let json = original.to_json().expect("to_json");
348        // `features` is a unit-only enum (bare PascalCase string);
349        // `actionTaker` uses AuthorizedActionTakers' internally-tagged shape.
350        // `position` is u16 — JSON erases the size; the value path locks it.
351        assert_eq!(
352            json,
353            json!({
354                "features": "WithAllAdvancedActions",
355                "actionTaker": {"$type": "group", "position": 7},
356            })
357        );
358        let recovered = TokenConfigurationPreset::from_json(json).expect("from_json");
359        assert_eq!(original, recovered);
360    }
361
362    #[test]
363    fn preset_value_round_trip_with_full_wire_shape() {
364        let original = fixture();
365        let value = original.to_object().expect("to_object");
366        assert_eq!(
367            value,
368            platform_value!({
369                "features": "WithAllAdvancedActions",
370                "actionTaker": {"$type": "group", "position": 7u16},
371            })
372        );
373        let recovered = TokenConfigurationPreset::from_object(value).expect("from_object");
374        assert_eq!(original, recovered);
375    }
376
377    #[test]
378    fn preset_features_round_trips_all_variants() {
379        let cases = [
380            (
381                TokenConfigurationPresetFeatures::MostRestrictive,
382                "MostRestrictive",
383            ),
384            (
385                TokenConfigurationPresetFeatures::WithOnlyEmergencyAction,
386                "WithOnlyEmergencyAction",
387            ),
388            (
389                TokenConfigurationPresetFeatures::WithMintingAndBurningActions,
390                "WithMintingAndBurningActions",
391            ),
392            (
393                TokenConfigurationPresetFeatures::WithAllAdvancedActions,
394                "WithAllAdvancedActions",
395            ),
396            (
397                TokenConfigurationPresetFeatures::WithExtremeActions,
398                "WithExtremeActions",
399            ),
400        ];
401        for (original, expected) in cases {
402            let json_v = original.to_json().expect("to_json");
403            assert_eq!(json_v, json!(expected));
404            assert_eq!(
405                TokenConfigurationPresetFeatures::from_json(json_v).expect("from_json"),
406                original
407            );
408            let value = original.to_object().expect("to_object");
409            assert_eq!(value, platform_value!(expected));
410            assert_eq!(
411                TokenConfigurationPresetFeatures::from_object(value).expect("from_object"),
412                original
413            );
414        }
415    }
416}
417
418impl TokenConfigurationPreset {
419    pub fn default_main_control_group_can_be_modified(&self) -> AuthorizedActionTakers {
420        match self.features {
421            TokenConfigurationPresetFeatures::MostRestrictive
422            | TokenConfigurationPresetFeatures::WithOnlyEmergencyAction
423            | TokenConfigurationPresetFeatures::WithMintingAndBurningActions
424            | TokenConfigurationPresetFeatures::WithAllAdvancedActions => {
425                AuthorizedActionTakers::NoOne
426            }
427            TokenConfigurationPresetFeatures::WithExtremeActions => self.action_taker,
428        }
429    }
430    pub fn default_basic_change_control_rules_v0(&self) -> ChangeControlRulesV0 {
431        match self.features {
432            TokenConfigurationPresetFeatures::MostRestrictive
433            | TokenConfigurationPresetFeatures::WithOnlyEmergencyAction => ChangeControlRulesV0 {
434                authorized_to_make_change: AuthorizedActionTakers::NoOne,
435                admin_action_takers: AuthorizedActionTakers::NoOne,
436                changing_authorized_action_takers_to_no_one_allowed: false,
437                changing_admin_action_takers_to_no_one_allowed: false,
438                self_changing_admin_action_takers_allowed: false,
439            },
440            TokenConfigurationPresetFeatures::WithMintingAndBurningActions
441            | TokenConfigurationPresetFeatures::WithAllAdvancedActions => ChangeControlRulesV0 {
442                authorized_to_make_change: self.action_taker,
443                admin_action_takers: self.action_taker,
444                changing_authorized_action_takers_to_no_one_allowed: false,
445                changing_admin_action_takers_to_no_one_allowed: false,
446                self_changing_admin_action_takers_allowed: true,
447            },
448            TokenConfigurationPresetFeatures::WithExtremeActions => ChangeControlRulesV0 {
449                authorized_to_make_change: self.action_taker,
450                admin_action_takers: self.action_taker,
451                changing_authorized_action_takers_to_no_one_allowed: true,
452                changing_admin_action_takers_to_no_one_allowed: true,
453                self_changing_admin_action_takers_allowed: true,
454            },
455        }
456    }
457
458    pub fn default_advanced_change_control_rules_v0(&self) -> ChangeControlRulesV0 {
459        match self.features {
460            TokenConfigurationPresetFeatures::MostRestrictive
461            | TokenConfigurationPresetFeatures::WithOnlyEmergencyAction
462            | TokenConfigurationPresetFeatures::WithMintingAndBurningActions => {
463                ChangeControlRulesV0 {
464                    authorized_to_make_change: AuthorizedActionTakers::NoOne,
465                    admin_action_takers: AuthorizedActionTakers::NoOne,
466                    changing_authorized_action_takers_to_no_one_allowed: false,
467                    changing_admin_action_takers_to_no_one_allowed: false,
468                    self_changing_admin_action_takers_allowed: false,
469                }
470            }
471            TokenConfigurationPresetFeatures::WithAllAdvancedActions => ChangeControlRulesV0 {
472                authorized_to_make_change: self.action_taker,
473                admin_action_takers: self.action_taker,
474                changing_authorized_action_takers_to_no_one_allowed: false,
475                changing_admin_action_takers_to_no_one_allowed: false,
476                self_changing_admin_action_takers_allowed: true,
477            },
478            TokenConfigurationPresetFeatures::WithExtremeActions => ChangeControlRulesV0 {
479                authorized_to_make_change: self.action_taker,
480                admin_action_takers: self.action_taker,
481                changing_authorized_action_takers_to_no_one_allowed: true,
482                changing_admin_action_takers_to_no_one_allowed: true,
483                self_changing_admin_action_takers_allowed: true,
484            },
485        }
486    }
487
488    pub fn default_emergency_action_change_control_rules_v0(&self) -> ChangeControlRulesV0 {
489        match self.features {
490            TokenConfigurationPresetFeatures::MostRestrictive => ChangeControlRulesV0 {
491                authorized_to_make_change: AuthorizedActionTakers::NoOne,
492                admin_action_takers: AuthorizedActionTakers::NoOne,
493                changing_authorized_action_takers_to_no_one_allowed: false,
494                changing_admin_action_takers_to_no_one_allowed: false,
495                self_changing_admin_action_takers_allowed: false,
496            },
497            TokenConfigurationPresetFeatures::WithAllAdvancedActions
498            | TokenConfigurationPresetFeatures::WithMintingAndBurningActions
499            | TokenConfigurationPresetFeatures::WithOnlyEmergencyAction => ChangeControlRulesV0 {
500                authorized_to_make_change: self.action_taker,
501                admin_action_takers: self.action_taker,
502                changing_authorized_action_takers_to_no_one_allowed: false,
503                changing_admin_action_takers_to_no_one_allowed: false,
504                self_changing_admin_action_takers_allowed: true,
505            },
506            TokenConfigurationPresetFeatures::WithExtremeActions => ChangeControlRulesV0 {
507                authorized_to_make_change: self.action_taker,
508                admin_action_takers: self.action_taker,
509                changing_authorized_action_takers_to_no_one_allowed: true,
510                changing_admin_action_takers_to_no_one_allowed: true,
511                self_changing_admin_action_takers_allowed: true,
512            },
513        }
514    }
515
516    pub fn default_distribution_rules_v0(
517        &self,
518        perpetual_distribution: Option<TokenPerpetualDistribution>,
519        pre_programmed_distribution: Option<TokenPreProgrammedDistribution>,
520        with_direct_pricing: bool,
521    ) -> TokenDistributionRulesV0 {
522        TokenDistributionRulesV0 {
523            perpetual_distribution,
524            perpetual_distribution_rules: self.default_advanced_change_control_rules_v0().into(),
525            pre_programmed_distribution,
526            new_tokens_destination_identity: None,
527            new_tokens_destination_identity_rules: self
528                .default_basic_change_control_rules_v0()
529                .into(),
530            minting_allow_choosing_destination: true,
531            minting_allow_choosing_destination_rules: self
532                .default_basic_change_control_rules_v0()
533                .into(),
534            change_direct_purchase_pricing_rules: if with_direct_pricing {
535                self.default_basic_change_control_rules_v0().into()
536            } else {
537                ChangeControlRulesV0 {
538                    authorized_to_make_change: AuthorizedActionTakers::NoOne,
539                    admin_action_takers: AuthorizedActionTakers::NoOne,
540                    changing_authorized_action_takers_to_no_one_allowed: false,
541                    changing_admin_action_takers_to_no_one_allowed: false,
542                    self_changing_admin_action_takers_allowed: false,
543                }
544                .into()
545            },
546        }
547    }
548
549    pub fn default_marketplace_rules_v0(&self) -> TokenMarketplaceRulesV0 {
550        TokenMarketplaceRulesV0 {
551            trade_mode: TokenTradeMode::NotTradeable,
552            trade_mode_change_rules: self.default_basic_change_control_rules_v0().into(),
553        }
554    }
555
556    pub fn token_configuration_v0(
557        &self,
558        conventions: TokenConfigurationConvention,
559        base_supply: TokenAmount,
560        max_supply: Option<TokenAmount>,
561        keeps_all_history: bool,
562        with_direct_pricing: bool,
563    ) -> TokenConfigurationV0 {
564        TokenConfigurationV0 {
565            conventions,
566            conventions_change_rules: self.default_basic_change_control_rules_v0().into(),
567            base_supply,
568            max_supply,
569            keeps_history: TokenKeepsHistoryRulesV0::default_for_keeping_all_history(
570                keeps_all_history,
571            )
572            .into(),
573            start_as_paused: false,
574            allow_transfer_to_frozen_balance: true,
575            max_supply_change_rules: self.default_advanced_change_control_rules_v0().into(),
576            distribution_rules: self
577                .default_distribution_rules_v0(None, None, with_direct_pricing)
578                .into(),
579            marketplace_rules: self.default_marketplace_rules_v0().into(),
580            manual_minting_rules: self.default_basic_change_control_rules_v0().into(),
581            manual_burning_rules: self.default_basic_change_control_rules_v0().into(),
582            freeze_rules: self.default_advanced_change_control_rules_v0().into(),
583            unfreeze_rules: self.default_advanced_change_control_rules_v0().into(),
584            destroy_frozen_funds_rules: self.default_advanced_change_control_rules_v0().into(),
585            emergency_action_rules: self
586                .default_emergency_action_change_control_rules_v0()
587                .into(),
588            main_control_group: None,
589            main_control_group_can_be_modified: self.default_main_control_group_can_be_modified(),
590            description: None,
591        }
592    }
593}
594
595impl TokenConfigurationV0 {
596    pub fn default_most_restrictive() -> Self {
597        TokenConfigurationPreset {
598            features: TokenConfigurationPresetFeatures::MostRestrictive,
599            action_taker: AuthorizedActionTakers::NoOne,
600        }
601        .token_configuration_v0(
602            TokenConfigurationConvention::V0(TokenConfigurationConventionV0 {
603                localizations: Default::default(),
604                decimals: 8,
605            }),
606            100000,
607            None,
608            true,
609            false,
610        )
611    }
612
613    pub fn with_base_supply(mut self, base_supply: TokenAmount) -> Self {
614        self.base_supply = base_supply;
615        self
616    }
617}
618
619#[cfg(test)]
620mod tests {
621    use super::*;
622    use crate::data_contract::associated_token::token_configuration::accessors::v0::{
623        TokenConfigurationV0Getters, TokenConfigurationV0Setters,
624    };
625    use platform_value::Identifier;
626
627    fn preset(
628        features: TokenConfigurationPresetFeatures,
629        action_taker: AuthorizedActionTakers,
630    ) -> TokenConfigurationPreset {
631        TokenConfigurationPreset {
632            features,
633            action_taker,
634        }
635    }
636
637    // --- default_main_control_group_can_be_modified ---
638
639    #[test]
640    fn preset_main_control_group_can_be_modified_most_restrictive_is_no_one() {
641        let p = preset(
642            TokenConfigurationPresetFeatures::MostRestrictive,
643            AuthorizedActionTakers::ContractOwner,
644        );
645        assert_eq!(
646            p.default_main_control_group_can_be_modified(),
647            AuthorizedActionTakers::NoOne
648        );
649    }
650
651    #[test]
652    fn preset_main_control_group_can_be_modified_only_emergency_is_no_one() {
653        let p = preset(
654            TokenConfigurationPresetFeatures::WithOnlyEmergencyAction,
655            AuthorizedActionTakers::ContractOwner,
656        );
657        assert_eq!(
658            p.default_main_control_group_can_be_modified(),
659            AuthorizedActionTakers::NoOne
660        );
661    }
662
663    #[test]
664    fn preset_main_control_group_can_be_modified_minting_burning_is_no_one() {
665        let p = preset(
666            TokenConfigurationPresetFeatures::WithMintingAndBurningActions,
667            AuthorizedActionTakers::ContractOwner,
668        );
669        assert_eq!(
670            p.default_main_control_group_can_be_modified(),
671            AuthorizedActionTakers::NoOne
672        );
673    }
674
675    #[test]
676    fn preset_main_control_group_can_be_modified_advanced_is_no_one() {
677        let p = preset(
678            TokenConfigurationPresetFeatures::WithAllAdvancedActions,
679            AuthorizedActionTakers::ContractOwner,
680        );
681        assert_eq!(
682            p.default_main_control_group_can_be_modified(),
683            AuthorizedActionTakers::NoOne
684        );
685    }
686
687    #[test]
688    fn preset_main_control_group_can_be_modified_extreme_is_action_taker() {
689        let taker = AuthorizedActionTakers::Identity(Identifier::from([9u8; 32]));
690        let p = preset(TokenConfigurationPresetFeatures::WithExtremeActions, taker);
691        assert_eq!(p.default_main_control_group_can_be_modified(), taker);
692    }
693
694    // --- default_basic_change_control_rules_v0 ---
695
696    #[test]
697    fn preset_basic_rules_most_restrictive_is_no_one_locked() {
698        let p = preset(
699            TokenConfigurationPresetFeatures::MostRestrictive,
700            AuthorizedActionTakers::ContractOwner,
701        );
702        let rules = p.default_basic_change_control_rules_v0();
703        assert_eq!(
704            rules.authorized_to_make_change,
705            AuthorizedActionTakers::NoOne
706        );
707        assert_eq!(rules.admin_action_takers, AuthorizedActionTakers::NoOne);
708        assert!(!rules.changing_authorized_action_takers_to_no_one_allowed);
709        assert!(!rules.changing_admin_action_takers_to_no_one_allowed);
710        assert!(!rules.self_changing_admin_action_takers_allowed);
711    }
712
713    #[test]
714    fn preset_basic_rules_only_emergency_is_no_one_locked() {
715        let p = preset(
716            TokenConfigurationPresetFeatures::WithOnlyEmergencyAction,
717            AuthorizedActionTakers::ContractOwner,
718        );
719        let rules = p.default_basic_change_control_rules_v0();
720        assert_eq!(
721            rules.authorized_to_make_change,
722            AuthorizedActionTakers::NoOne
723        );
724    }
725
726    #[test]
727    fn preset_basic_rules_minting_burning_is_action_taker_self_mutable() {
728        let taker = AuthorizedActionTakers::ContractOwner;
729        let p = preset(
730            TokenConfigurationPresetFeatures::WithMintingAndBurningActions,
731            taker,
732        );
733        let rules = p.default_basic_change_control_rules_v0();
734        assert_eq!(rules.authorized_to_make_change, taker);
735        assert_eq!(rules.admin_action_takers, taker);
736        assert!(rules.self_changing_admin_action_takers_allowed);
737        // but not to no-one
738        assert!(!rules.changing_authorized_action_takers_to_no_one_allowed);
739    }
740
741    #[test]
742    fn preset_basic_rules_advanced_is_action_taker_self_mutable() {
743        let taker = AuthorizedActionTakers::ContractOwner;
744        let p = preset(
745            TokenConfigurationPresetFeatures::WithAllAdvancedActions,
746            taker,
747        );
748        let rules = p.default_basic_change_control_rules_v0();
749        assert_eq!(rules.authorized_to_make_change, taker);
750        assert!(rules.self_changing_admin_action_takers_allowed);
751        assert!(!rules.changing_admin_action_takers_to_no_one_allowed);
752    }
753
754    #[test]
755    fn preset_basic_rules_extreme_allows_no_one_transitions() {
756        let taker = AuthorizedActionTakers::ContractOwner;
757        let p = preset(TokenConfigurationPresetFeatures::WithExtremeActions, taker);
758        let rules = p.default_basic_change_control_rules_v0();
759        assert_eq!(rules.authorized_to_make_change, taker);
760        assert!(rules.changing_authorized_action_takers_to_no_one_allowed);
761        assert!(rules.changing_admin_action_takers_to_no_one_allowed);
762        assert!(rules.self_changing_admin_action_takers_allowed);
763    }
764
765    // --- default_advanced_change_control_rules_v0 ---
766
767    #[test]
768    fn preset_advanced_rules_most_restrictive_is_locked() {
769        let p = preset(
770            TokenConfigurationPresetFeatures::MostRestrictive,
771            AuthorizedActionTakers::ContractOwner,
772        );
773        let rules = p.default_advanced_change_control_rules_v0();
774        assert_eq!(
775            rules.authorized_to_make_change,
776            AuthorizedActionTakers::NoOne
777        );
778        assert!(!rules.self_changing_admin_action_takers_allowed);
779    }
780
781    #[test]
782    fn preset_advanced_rules_minting_burning_is_locked() {
783        let p = preset(
784            TokenConfigurationPresetFeatures::WithMintingAndBurningActions,
785            AuthorizedActionTakers::ContractOwner,
786        );
787        // Minting/burning does NOT open up advanced operations -> advanced remains NoOne
788        let rules = p.default_advanced_change_control_rules_v0();
789        assert_eq!(
790            rules.authorized_to_make_change,
791            AuthorizedActionTakers::NoOne
792        );
793        assert_eq!(rules.admin_action_takers, AuthorizedActionTakers::NoOne);
794    }
795
796    #[test]
797    fn preset_advanced_rules_only_emergency_is_locked() {
798        let p = preset(
799            TokenConfigurationPresetFeatures::WithOnlyEmergencyAction,
800            AuthorizedActionTakers::ContractOwner,
801        );
802        let rules = p.default_advanced_change_control_rules_v0();
803        assert_eq!(
804            rules.authorized_to_make_change,
805            AuthorizedActionTakers::NoOne
806        );
807    }
808
809    #[test]
810    fn preset_advanced_rules_advanced_allows_action_taker() {
811        let taker = AuthorizedActionTakers::ContractOwner;
812        let p = preset(
813            TokenConfigurationPresetFeatures::WithAllAdvancedActions,
814            taker,
815        );
816        let rules = p.default_advanced_change_control_rules_v0();
817        assert_eq!(rules.authorized_to_make_change, taker);
818        assert!(rules.self_changing_admin_action_takers_allowed);
819        assert!(!rules.changing_authorized_action_takers_to_no_one_allowed);
820    }
821
822    #[test]
823    fn preset_advanced_rules_extreme_allows_everything() {
824        let taker = AuthorizedActionTakers::ContractOwner;
825        let p = preset(TokenConfigurationPresetFeatures::WithExtremeActions, taker);
826        let rules = p.default_advanced_change_control_rules_v0();
827        assert!(rules.changing_authorized_action_takers_to_no_one_allowed);
828        assert!(rules.changing_admin_action_takers_to_no_one_allowed);
829        assert!(rules.self_changing_admin_action_takers_allowed);
830    }
831
832    // --- default_emergency_action_change_control_rules_v0 ---
833
834    #[test]
835    fn preset_emergency_rules_most_restrictive_is_no_one() {
836        let p = preset(
837            TokenConfigurationPresetFeatures::MostRestrictive,
838            AuthorizedActionTakers::ContractOwner,
839        );
840        let rules = p.default_emergency_action_change_control_rules_v0();
841        assert_eq!(
842            rules.authorized_to_make_change,
843            AuthorizedActionTakers::NoOne
844        );
845    }
846
847    #[test]
848    fn preset_emergency_rules_only_emergency_allows_action_taker() {
849        let taker = AuthorizedActionTakers::ContractOwner;
850        let p = preset(
851            TokenConfigurationPresetFeatures::WithOnlyEmergencyAction,
852            taker,
853        );
854        let rules = p.default_emergency_action_change_control_rules_v0();
855        assert_eq!(rules.authorized_to_make_change, taker);
856        assert!(rules.self_changing_admin_action_takers_allowed);
857    }
858
859    #[test]
860    fn preset_emergency_rules_minting_burning_allows_action_taker() {
861        let taker = AuthorizedActionTakers::ContractOwner;
862        let p = preset(
863            TokenConfigurationPresetFeatures::WithMintingAndBurningActions,
864            taker,
865        );
866        let rules = p.default_emergency_action_change_control_rules_v0();
867        assert_eq!(rules.authorized_to_make_change, taker);
868        assert!(rules.self_changing_admin_action_takers_allowed);
869    }
870
871    #[test]
872    fn preset_emergency_rules_advanced_allows_action_taker() {
873        let taker = AuthorizedActionTakers::ContractOwner;
874        let p = preset(
875            TokenConfigurationPresetFeatures::WithAllAdvancedActions,
876            taker,
877        );
878        let rules = p.default_emergency_action_change_control_rules_v0();
879        assert_eq!(rules.authorized_to_make_change, taker);
880    }
881
882    #[test]
883    fn preset_emergency_rules_extreme_allows_no_one_transitions() {
884        let taker = AuthorizedActionTakers::ContractOwner;
885        let p = preset(TokenConfigurationPresetFeatures::WithExtremeActions, taker);
886        let rules = p.default_emergency_action_change_control_rules_v0();
887        assert!(rules.changing_authorized_action_takers_to_no_one_allowed);
888    }
889
890    // --- default_distribution_rules_v0 with/without direct pricing ---
891
892    #[test]
893    fn preset_distribution_rules_with_direct_pricing_uses_basic_rules() {
894        let taker = AuthorizedActionTakers::ContractOwner;
895        let p = preset(TokenConfigurationPresetFeatures::WithExtremeActions, taker);
896        let rules = p.default_distribution_rules_v0(None, None, true);
897        // With direct pricing enabled, the rules match basic (extreme -> owner, all permissive)
898        assert_eq!(
899            rules
900                .change_direct_purchase_pricing_rules
901                .authorized_to_make_change_action_takers(),
902            &taker
903        );
904    }
905
906    #[test]
907    fn preset_distribution_rules_without_direct_pricing_locks_it_down() {
908        let taker = AuthorizedActionTakers::ContractOwner;
909        let p = preset(TokenConfigurationPresetFeatures::WithExtremeActions, taker);
910        let rules = p.default_distribution_rules_v0(None, None, false);
911        // Without direct pricing, change_direct_purchase_pricing_rules is hard-coded to NoOne
912        assert_eq!(
913            rules
914                .change_direct_purchase_pricing_rules
915                .authorized_to_make_change_action_takers(),
916            &AuthorizedActionTakers::NoOne
917        );
918    }
919
920    #[test]
921    fn preset_distribution_rules_minting_choosing_destination_defaults_true() {
922        let p = preset(
923            TokenConfigurationPresetFeatures::MostRestrictive,
924            AuthorizedActionTakers::NoOne,
925        );
926        let rules = p.default_distribution_rules_v0(None, None, false);
927        assert!(rules.minting_allow_choosing_destination);
928        assert!(rules.new_tokens_destination_identity.is_none());
929        assert!(rules.perpetual_distribution.is_none());
930        assert!(rules.pre_programmed_distribution.is_none());
931    }
932
933    // --- default_marketplace_rules_v0 ---
934
935    #[test]
936    fn preset_marketplace_rules_default_is_not_tradeable() {
937        let p = preset(
938            TokenConfigurationPresetFeatures::MostRestrictive,
939            AuthorizedActionTakers::NoOne,
940        );
941        let mp = p.default_marketplace_rules_v0();
942        assert_eq!(mp.trade_mode, TokenTradeMode::NotTradeable);
943    }
944
945    // --- token_configuration_v0 full config ---
946
947    #[test]
948    fn preset_token_configuration_v0_populates_fields() {
949        let taker = AuthorizedActionTakers::ContractOwner;
950        let p = preset(TokenConfigurationPresetFeatures::WithExtremeActions, taker);
951        let conventions = TokenConfigurationConvention::V0(TokenConfigurationConventionV0 {
952            localizations: Default::default(),
953            decimals: 4,
954        });
955        let config = p.token_configuration_v0(conventions, 1_000, Some(5_000), true, true);
956        assert_eq!(config.base_supply, 1_000);
957        assert_eq!(config.max_supply, Some(5_000));
958        assert_eq!(
959            config
960                .manual_minting_rules
961                .authorized_to_make_change_action_takers(),
962            &taker
963        );
964        // start_as_paused is fixed false by constructor
965        assert!(!config.start_as_paused);
966        assert!(config.allow_transfer_to_frozen_balance);
967        assert_eq!(config.main_control_group, None);
968        // extreme => main_control_group_can_be_modified becomes taker
969        assert_eq!(config.main_control_group_can_be_modified, taker);
970        // description is none
971        assert!(config.description.is_none());
972    }
973
974    #[test]
975    fn preset_token_configuration_keeps_all_history_true() {
976        let p = preset(
977            TokenConfigurationPresetFeatures::MostRestrictive,
978            AuthorizedActionTakers::NoOne,
979        );
980        let conventions = TokenConfigurationConvention::V0(TokenConfigurationConventionV0 {
981            localizations: Default::default(),
982            decimals: 8,
983        });
984        let cfg = p.token_configuration_v0(conventions, 100, None, true, false);
985        // keeps_history is TokenKeepsHistoryRules::V0; all fields should be true
986        match &cfg.keeps_history {
987            TokenKeepsHistoryRules::V0(v0) => {
988                assert!(v0.keeps_transfer_history);
989                assert!(v0.keeps_freezing_history);
990                assert!(v0.keeps_minting_history);
991                assert!(v0.keeps_burning_history);
992                assert!(v0.keeps_direct_pricing_history);
993                assert!(v0.keeps_direct_purchase_history);
994            }
995        }
996    }
997
998    #[test]
999    fn preset_token_configuration_keeps_all_history_false() {
1000        let p = preset(
1001            TokenConfigurationPresetFeatures::MostRestrictive,
1002            AuthorizedActionTakers::NoOne,
1003        );
1004        let conventions = TokenConfigurationConvention::V0(TokenConfigurationConventionV0 {
1005            localizations: Default::default(),
1006            decimals: 8,
1007        });
1008        let cfg = p.token_configuration_v0(conventions, 100, None, false, false);
1009        match &cfg.keeps_history {
1010            TokenKeepsHistoryRules::V0(v0) => {
1011                assert!(!v0.keeps_transfer_history);
1012                assert!(!v0.keeps_direct_purchase_history);
1013            }
1014        }
1015    }
1016
1017    // --- default_most_restrictive + with_base_supply chaining ---
1018
1019    #[test]
1020    fn token_configuration_v0_default_most_restrictive_has_no_max_supply() {
1021        let c = TokenConfigurationV0::default_most_restrictive();
1022        assert_eq!(c.base_supply, 100_000);
1023        assert!(c.max_supply.is_none());
1024        assert_eq!(
1025            c.main_control_group_can_be_modified,
1026            AuthorizedActionTakers::NoOne
1027        );
1028    }
1029
1030    #[test]
1031    fn token_configuration_v0_with_base_supply_overrides_value() {
1032        let c = TokenConfigurationV0::default_most_restrictive().with_base_supply(42);
1033        assert_eq!(c.base_supply, 42);
1034    }
1035
1036    // --- Display trait ---
1037
1038    #[test]
1039    fn display_token_configuration_v0_contains_key_fields() {
1040        let c = TokenConfigurationV0::default_most_restrictive();
1041        let s = format!("{}", c);
1042        assert!(s.contains("TokenConfigurationV0"));
1043        assert!(s.contains("base_supply"));
1044        assert!(s.contains("main_control_group"));
1045    }
1046
1047    // --- all_used_group_positions: the interesting branches ---
1048
1049    #[test]
1050    fn all_used_group_positions_empty_when_no_groups_referenced() {
1051        let c = TokenConfigurationV0::default_most_restrictive();
1052        let (positions, uses_main) = c.all_used_group_positions();
1053        assert!(positions.is_empty());
1054        assert!(!uses_main);
1055    }
1056
1057    #[test]
1058    fn all_used_group_positions_collects_from_group_variant_in_rules() {
1059        let mut c = TokenConfigurationV0::default_most_restrictive();
1060        c.freeze_rules = ChangeControlRules::V0(ChangeControlRulesV0 {
1061            authorized_to_make_change: AuthorizedActionTakers::Group(7),
1062            admin_action_takers: AuthorizedActionTakers::Group(9),
1063            changing_authorized_action_takers_to_no_one_allowed: false,
1064            changing_admin_action_takers_to_no_one_allowed: false,
1065            self_changing_admin_action_takers_allowed: false,
1066        });
1067        let (positions, uses_main) = c.all_used_group_positions();
1068        assert!(positions.contains(&7));
1069        assert!(positions.contains(&9));
1070        assert!(!uses_main);
1071    }
1072
1073    #[test]
1074    fn all_used_group_positions_flags_main_group_usage() {
1075        let mut c = TokenConfigurationV0::default_most_restrictive();
1076        c.emergency_action_rules = ChangeControlRules::V0(ChangeControlRulesV0 {
1077            authorized_to_make_change: AuthorizedActionTakers::MainGroup,
1078            admin_action_takers: AuthorizedActionTakers::NoOne,
1079            changing_authorized_action_takers_to_no_one_allowed: false,
1080            changing_admin_action_takers_to_no_one_allowed: false,
1081            self_changing_admin_action_takers_allowed: false,
1082        });
1083        let (_, uses_main) = c.all_used_group_positions();
1084        assert!(uses_main);
1085    }
1086
1087    #[test]
1088    fn all_used_group_positions_includes_main_control_group() {
1089        let mut c = TokenConfigurationV0::default_most_restrictive();
1090        c.main_control_group = Some(42);
1091        let (positions, _) = c.all_used_group_positions();
1092        assert!(positions.contains(&42));
1093    }
1094
1095    #[test]
1096    fn all_used_group_positions_includes_positions_from_main_control_group_can_be_modified() {
1097        let mut c = TokenConfigurationV0::default_most_restrictive();
1098        c.main_control_group_can_be_modified = AuthorizedActionTakers::Group(11);
1099        let (positions, _) = c.all_used_group_positions();
1100        assert!(positions.contains(&11));
1101    }
1102
1103    #[test]
1104    fn all_used_group_positions_ignores_contract_owner_and_identity_and_no_one() {
1105        let mut c = TokenConfigurationV0::default_most_restrictive();
1106        c.manual_minting_rules = ChangeControlRules::V0(ChangeControlRulesV0 {
1107            authorized_to_make_change: AuthorizedActionTakers::ContractOwner,
1108            admin_action_takers: AuthorizedActionTakers::Identity(Identifier::from([1u8; 32])),
1109            changing_authorized_action_takers_to_no_one_allowed: false,
1110            changing_admin_action_takers_to_no_one_allowed: false,
1111            self_changing_admin_action_takers_allowed: false,
1112        });
1113        let (positions, uses_main) = c.all_used_group_positions();
1114        assert!(positions.is_empty());
1115        assert!(!uses_main);
1116    }
1117
1118    // --- all_change_control_rules ---
1119
1120    #[test]
1121    fn all_change_control_rules_returns_expected_rule_names() {
1122        let c = TokenConfigurationV0::default_most_restrictive();
1123        let rules = c.all_change_control_rules();
1124        let names: Vec<&str> = rules.iter().map(|(name, _)| *name).collect();
1125        assert!(names.contains(&"max_supply_change_rules"));
1126        assert!(names.contains(&"conventions_change_rules"));
1127        assert!(names.contains(&"manual_minting_rules"));
1128        assert!(names.contains(&"manual_burning_rules"));
1129        assert!(names.contains(&"freeze_rules"));
1130        assert!(names.contains(&"unfreeze_rules"));
1131        assert!(names.contains(&"destroy_frozen_funds_rules"));
1132        assert!(names.contains(&"emergency_action_rules"));
1133        assert!(names.contains(&"trade_mode_change_rules"));
1134        // 13 rules total per the implementation
1135        assert_eq!(rules.len(), 13);
1136    }
1137
1138    // --- setters exercise the right fields ---
1139
1140    #[test]
1141    fn setters_set_description_max_supply_base_supply_main_control_group() {
1142        let mut c = TokenConfigurationV0::default_most_restrictive();
1143        c.set_description(Some("my token".to_string()));
1144        c.set_max_supply(Some(999));
1145        c.set_base_supply(77);
1146        c.set_main_control_group(Some(3));
1147        c.set_start_as_paused(true);
1148        c.allow_transfer_to_frozen_balance(false);
1149        c.set_main_control_group_can_be_modified(AuthorizedActionTakers::ContractOwner);
1150        assert_eq!(c.description(), &Some("my token".to_string()));
1151        assert_eq!(c.max_supply(), Some(999));
1152        assert_eq!(c.base_supply(), 77);
1153        assert_eq!(c.main_control_group(), Some(3));
1154        assert!(c.start_as_paused());
1155        assert!(!c.is_allowed_transfer_to_frozen_balance());
1156        assert_eq!(
1157            c.main_control_group_can_be_modified(),
1158            &AuthorizedActionTakers::ContractOwner
1159        );
1160    }
1161}