Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ impl TokenConfigurationV0 {
TokenConfigurationChangeItem::EmergencyActionAdminGroup(_) => {
*self.emergency_action_rules.admin_action_takers()
}
TokenConfigurationChangeItem::MainControlGroup(_) => AuthorizedActionTakers::NoOne,
TokenConfigurationChangeItem::MainControlGroup(_) => {
self.main_control_group_can_be_modified
}
TokenConfigurationChangeItem::MarketplaceTradeMode(_) => *self
.marketplace_rules
.trade_mode_change_rules()
Expand Down Expand Up @@ -267,18 +269,35 @@ mod tests {
}

#[test]
fn main_control_group_always_returns_no_one() {
// Per implementation, MainControlGroup change items always return NoOne,
// regardless of config. This is important because modifying the main
// control group is governed by main_control_group_can_be_modified, not
// by any of the change_control_rules.
let c = config_with_all_owner_rules();
fn main_control_group_returns_no_one_by_default() {
// default_most_restrictive leaves main_control_group_can_be_modified as NoOne
let c = TokenConfigurationV0::default_most_restrictive();
let result = c.authorized_action_takers_for_configuration_item(
&TokenConfigurationChangeItem::MainControlGroup(Some(3)),
);
assert_eq!(result, AuthorizedActionTakers::NoOne);
}

#[test]
fn main_control_group_returns_configured_can_be_modified() {
// Modifying the main control group is governed by
// main_control_group_can_be_modified, not by any of the
// change_control_rules, so that is what must be reported here.
for takers in [
AuthorizedActionTakers::ContractOwner,
AuthorizedActionTakers::MainGroup,
AuthorizedActionTakers::Group(0),
AuthorizedActionTakers::Identity(Identifier::from([7u8; 32])),
] {
let mut c = TokenConfigurationV0::default_most_restrictive();
c.set_main_control_group_can_be_modified(takers);
let result = c.authorized_action_takers_for_configuration_item(
&TokenConfigurationChangeItem::MainControlGroup(Some(3)),
);
assert_eq!(result, takers);
}
}

#[test]
fn marketplace_trade_mode_returns_authorized_to_make_change() {
let c = TokenConfigurationV0::default_most_restrictive();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,199 @@ mod token_config_update_tests {
assert_eq!(updated_token_config.max_supply(), Some(1000000));
}

#[tokio::test]
async fn test_token_config_update_by_group_member_changing_main_control_group() {
let platform_version = PlatformVersion::latest();
let mut platform = TestPlatformBuilder::new()
.with_latest_protocol_version()
.build_with_mock_rpc()
.set_genesis_state();

let mut rng = StdRng::seed_from_u64(49853);

let platform_state = platform.state.load();

let (identity, signer, key) =
setup_identity(&mut platform, rng.gen(), dash_to_credits!(0.5));

let (identity_2, signer_2, key_2) =
setup_identity(&mut platform, rng.gen(), dash_to_credits!(0.5));

let (contract, token_id) = create_token_contract_with_owner_identity(
&mut platform,
identity.id(),
Some(|token_configuration: &mut TokenConfiguration| {
token_configuration
.set_main_control_group_can_be_modified(AuthorizedActionTakers::Group(0));
}),
None,
Some(
[(
0,
Group::V0(GroupV0 {
members: [(identity.id(), 1), (identity_2.id(), 1)].into(),
required_power: 2,
}),
)]
.into(),
),
None,
platform_version,
);

let action_id = TokenConfigUpdateTransition::calculate_action_id_with_fields(
token_id.as_bytes(),
identity.id().as_bytes(),
2,
&TokenConfigurationChangeItem::MainControlGroup(Some(0)),
platform_version,
)
.expect("expected to calculate action id");

let config_update_transition = BatchTransition::new_token_config_update_transition(
token_id,
identity.id(),
contract.id(),
0,
TokenConfigurationChangeItem::MainControlGroup(Some(0)),
None,
Some(GroupStateTransitionInfoStatus::GroupStateTransitionInfoProposer(0)),
&key,
2,
0,
&signer,
platform_version,
None,
)
.await
.expect("expect to create documents batch transition");

let config_update_transition_serialized_transition = config_update_transition
.serialize_to_bytes()
.expect("expected documents batch serialized state transition");

let transaction = platform.drive.grove.start_transaction();

let processing_result = platform
.platform
.process_raw_state_transitions(
&[config_update_transition_serialized_transition.clone()],
&platform_state,
&BlockInfo::default(),
&transaction,
platform_version,
false,
None,
)
.expect("expected to process state transition");

assert_matches!(
processing_result.execution_results().as_slice(),
[StateTransitionExecutionResult::SuccessfulExecution { .. }]
);

platform
.drive
.grove
.commit_transaction(transaction)
.unwrap()
.expect("expected to commit transaction");

let new_contract = platform
.drive
.fetch_contract(
contract.id().to_buffer(),
None,
None,
None,
platform_version,
)
.unwrap()
.expect("expected to fetch contract")
.expect("expected contract");
let updated_token_config = new_contract
.contract
.expected_token_configuration(0)
.expect("expected token configuration");
// only proposed so far, group power 1 of required 2
assert_eq!(updated_token_config.main_control_group(), None);

let config_update_transition = BatchTransition::new_token_config_update_transition(
token_id,
identity_2.id(),
contract.id(),
0,
TokenConfigurationChangeItem::MainControlGroup(Some(0)),
None,
Some(
GroupStateTransitionInfoStatus::GroupStateTransitionInfoOtherSigner(
GroupStateTransitionInfo {
group_contract_position: 0,
action_id,
action_is_proposer: false,
},
),
),
&key_2,
2,
0,
&signer_2,
platform_version,
None,
)
.await
.expect("expect to create documents batch transition");

let config_update_transition_serialized_transition = config_update_transition
.serialize_to_bytes()
.expect("expected documents batch serialized state transition");

let transaction = platform.drive.grove.start_transaction();

let processing_result = platform
.platform
.process_raw_state_transitions(
&[config_update_transition_serialized_transition.clone()],
&platform_state,
&BlockInfo::default(),
&transaction,
platform_version,
false,
None,
)
.expect("expected to process state transition");

assert_matches!(
processing_result.execution_results().as_slice(),
[StateTransitionExecutionResult::SuccessfulExecution { .. }]
);

platform
.drive
.grove
.commit_transaction(transaction)
.unwrap()
.expect("expected to commit transaction");

let new_contract = platform
.drive
.fetch_contract(
contract.id().to_buffer(),
None,
None,
None,
platform_version,
)
.unwrap()
.expect("expected to fetch contract")
.expect("expected contract");
let updated_token_config = new_contract
.contract
.expected_token_configuration(0)
.expect("expected token configuration");
assert_eq!(updated_token_config.main_control_group(), Some(0));
}

#[tokio::test]
async fn test_token_config_update_by_group_member_changing_minting_destination_group() {
let platform_version = PlatformVersion::latest();
Expand Down
Loading