-
Notifications
You must be signed in to change notification settings - Fork 12
Fixes for issues reported in pentesting audit #338
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -188,15 +188,22 @@ module supra_framework::committee_map { | |
| // f+1, number of nodes in a family committee should be greater than 1 | ||
| assert!(num_of_nodes > 1, INVALID_NODE_NUMBERS); | ||
| } else if (committee_type == CLAN) { | ||
| // 2f+1, number of nodes in a clan committee should be odd and greater than 3 | ||
| // 2f+1, number of nodes in a clan committee should be odd and greater than or equal to 3 | ||
| assert!(num_of_nodes >= 3 && num_of_nodes % 2 == 1, INVALID_NODE_NUMBERS); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } else { | ||
| // 3f+1, number of nodes in a tribe committee should be in the format of 3f+1 and greater than 4 | ||
| // 3f+1, number of nodes in a tribe committee should be in the format of 3f+1 and greater than or equal to 4 | ||
| assert!(num_of_nodes >= 4 && (num_of_nodes - 1) % 3 == 0, INVALID_NODE_NUMBERS); | ||
| }; | ||
| committee_type | ||
| } | ||
|
|
||
| /// Ensures removing exactly one member keeps the committee type invariants valid. | ||
| fun validate_committee_type_after_member_removal(committee: &CommitteeInfo) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion for the function name: |
||
| let current_num_of_nodes = simple_map::length(&committee.map); | ||
| assert!(current_num_of_nodes > 0, INVALID_NODE_NUMBERS); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| validate_committee_type(committee.committee_type, current_num_of_nodes - 1); | ||
| } | ||
|
|
||
| #[view] | ||
| /// Get the committee's node vector and committee type | ||
| public fun get_committee_info(com_store_addr: address, id: u64): (vector<NodeData>, u8) acquires CommitteeInfoStore { | ||
|
|
@@ -545,6 +552,27 @@ module supra_framework::committee_map { | |
| let _acquire = &capability::acquire(owner_signer, &OwnerCap {}); | ||
|
|
||
| let committee_store = borrow_global_mut<CommitteeInfoStore>(com_store_addr); | ||
| let event_handler = borrow_global_mut<SupraCommitteeEventHandler>(get_committeeInfo_address(owner_signer)); | ||
|
|
||
| // If the node is already associated with another committee, remove the stale entry first. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure how we're using this module, but I know that when we eventually add support for Clans and Families (sub-committees) to the L1 that a node will be able to participate in multiple committees simultaneously. If we intend to use this module for that use case then There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For now, this is used for DORA nodes for discovery @dhaval-supraoracles , but yes, we can modify it to make it more general. |
||
| if (simple_map::contains_key(&committee_store.node_to_committee_map, &node_address)) { | ||
| let old_committee_id = *simple_map::borrow(&committee_store.node_to_committee_map, &node_address); | ||
| if (old_committee_id != id && simple_map::contains_key(&committee_store.committee_map, &old_committee_id)) { | ||
| let old_committee = simple_map::borrow_mut(&mut committee_store.committee_map, &old_committee_id); | ||
| if (does_node_exist(old_committee, node_address)) { | ||
| validate_committee_type_after_member_removal(old_committee); | ||
| let (_, old_node_info) = simple_map::remove(&mut old_committee.map, &node_address); | ||
| emit_event( | ||
| &mut event_handler.remove_committee_member, | ||
| RemoveCommitteeMemberEvent { | ||
| committee_id: old_committee_id, | ||
| committee_member: old_node_info | ||
| } | ||
| ) | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| let committee = simple_map::borrow_mut(&mut committee_store.committee_map, &id); | ||
| let node_info = NodeInfo { | ||
| ip_public_address: copy ip_public_address, | ||
|
|
@@ -554,7 +582,6 @@ module supra_framework::committee_map { | |
| network_port: network_port, | ||
| rpc_port: rpc_port, | ||
| }; | ||
| let event_handler = borrow_global_mut<SupraCommitteeEventHandler>(get_committeeInfo_address(owner_signer)); | ||
| if (!does_node_exist(committee, node_address)) { | ||
| emit_event( | ||
| &mut event_handler.add_committee_member, | ||
|
|
@@ -655,6 +682,7 @@ module supra_framework::committee_map { | |
| let committee_store = borrow_global_mut<CommitteeInfoStore>(com_store_addr); | ||
| let committee = simple_map::borrow_mut(&mut committee_store.committee_map, &id); | ||
| ensure_node_address_exist(committee, node_address); | ||
| validate_committee_type_after_member_removal(committee); | ||
| let (_, node_info) = simple_map::remove(&mut committee.map, &node_address); | ||
| let event_handler = borrow_global_mut<SupraCommitteeEventHandler>(get_committeeInfo_address(owner_signer)); | ||
| emit_event( | ||
|
|
@@ -880,6 +908,131 @@ module supra_framework::committee_map { | |
| ); | ||
| } | ||
|
|
||
| #[test(owner_signer = @0xCEFEF)] | ||
| #[expected_failure(abort_code = INVALID_NODE_NUMBERS, location = Self)] | ||
| public entry fun test_remove_committee_member_type_validation( | ||
| owner_signer: &signer | ||
| ) acquires CommitteeInfoStore, SupraCommitteeEventHandler { | ||
| set_up_test(owner_signer); | ||
| let resource_address = account::create_resource_address(&@0xCEFEF, SEED_COMMITTEE); | ||
| upsert_committee( | ||
| owner_signer, | ||
| resource_address, | ||
| 1, | ||
| vector[@0x1, @0x2], | ||
| vector[vector[123], vector[124]], | ||
| vector[vector[123], vector[124]], | ||
| vector[vector[123], vector[124]], | ||
| vector[vector[123], vector[124]], | ||
| vector[123, 124], | ||
| vector[123, 124], | ||
| FAMILY | ||
| ); | ||
| remove_committee_member(owner_signer, resource_address, 1, @0x1); | ||
| } | ||
|
|
||
| #[test(owner_signer = @0xCEFEF)] | ||
| #[expected_failure(abort_code = INVALID_NODE_NUMBERS, location = Self)] | ||
| public entry fun test_transfer_member_type_validation( | ||
| owner_signer: &signer | ||
| ) acquires CommitteeInfoStore, SupraCommitteeEventHandler { | ||
| set_up_test(owner_signer); | ||
| let resource_address = account::create_resource_address(&@0xCEFEF, SEED_COMMITTEE); | ||
| upsert_committee( | ||
| owner_signer, | ||
| resource_address, | ||
| 1, | ||
| vector[@0x1, @0x2], | ||
| vector[vector[123], vector[124]], | ||
| vector[vector[123], vector[124]], | ||
| vector[vector[123], vector[124]], | ||
| vector[vector[123], vector[124]], | ||
| vector[123, 124], | ||
| vector[123, 124], | ||
| FAMILY | ||
| ); | ||
| upsert_committee( | ||
| owner_signer, | ||
| resource_address, | ||
| 2, | ||
| vector[@0x3, @0x4], | ||
| vector[vector[125], vector[126]], | ||
| vector[vector[125], vector[126]], | ||
| vector[vector[125], vector[126]], | ||
| vector[vector[125], vector[126]], | ||
| vector[125, 126], | ||
| vector[125, 126], | ||
| FAMILY | ||
| ); | ||
| upsert_committee_member( | ||
| owner_signer, | ||
| resource_address, | ||
| 2, | ||
| @0x1, | ||
| vector[127], | ||
| vector[127], | ||
| vector[127], | ||
| vector[127], | ||
| 127, | ||
| 127 | ||
| ); | ||
| } | ||
|
|
||
| #[test(owner_signer = @0xCEFEF)] | ||
| public entry fun test_transfer_committee_member_removes_old_committee_entry( | ||
| owner_signer: &signer | ||
| ) acquires CommitteeInfoStore, SupraCommitteeEventHandler { | ||
| set_up_test(owner_signer); | ||
| let resource_address = account::create_resource_address(&@0xCEFEF, SEED_COMMITTEE); | ||
| upsert_committee( | ||
| owner_signer, | ||
| resource_address, | ||
| 1, | ||
| vector[@0x1, @0x2, @0x5], | ||
| vector[vector[123], vector[124], vector[125]], | ||
| vector[vector[123], vector[124], vector[125]], | ||
| vector[vector[123], vector[124], vector[125]], | ||
| vector[vector[123], vector[124], vector[125]], | ||
| vector[123, 124, 125], | ||
| vector[123, 124, 125], | ||
| 1 | ||
| ); | ||
| upsert_committee( | ||
| owner_signer, | ||
| resource_address, | ||
| 2, | ||
| vector[@0x3, @0x4], | ||
| vector[vector[125], vector[126]], | ||
| vector[vector[125], vector[126]], | ||
| vector[vector[125], vector[126]], | ||
| vector[vector[125], vector[126]], | ||
| vector[125, 126], | ||
| vector[125, 126], | ||
| 1 | ||
| ); | ||
| upsert_committee_member( | ||
| owner_signer, | ||
| resource_address, | ||
| 2, | ||
| @0x1, | ||
| vector[127], | ||
| vector[127], | ||
| vector[127], | ||
| vector[127], | ||
| 127, | ||
| 127 | ||
| ); | ||
|
|
||
| let (exists_in_old_committee, _) = find_node_in_committee(resource_address, 1, @0x1); | ||
| assert!(!exists_in_old_committee, 1); | ||
| assert!(get_committee_id(resource_address, @0x1) == 2, 2); | ||
| let (exists_in_new_committee, _) = find_node_in_committee(resource_address, 2, @0x1); | ||
| assert!(exists_in_new_committee, 3); | ||
|
|
||
| // Should succeed because node_to_committee_map and committee maps stay in sync. | ||
| remove_committee(owner_signer, resource_address, 1); | ||
| } | ||
|
|
||
| #[test(owner_signer = @0xCEFEF)] | ||
| public entry fun test_update_dkg_flag( | ||
| owner_signer: &signer | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -69,7 +69,7 @@ module supra_framework::config_buffer { | |
| /// Should only be used at the end of a reconfiguration. | ||
| /// | ||
| /// Typically used in `X::on_new_epoch()` where X is an on-chaon config. | ||
| public fun extract<T: store>(): T acquires PendingConfigs { | ||
| public(friend) fun extract<T: store>(): T acquires PendingConfigs { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With this we can't upgrade I think. which is included in fwk upgrade PR LINK There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @dhaval-supraoracles , has the necessary changes been done to the calling code? Are they now calling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes all relevant module also uses There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All modules that call this function need to be marked as I think a simpler change would be to add There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. agreed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, since the method does not take a
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @dhaval-supraoracles Can we make this change in the upcoming FWK upgrade? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's already updated on FWK upgrade changes. @supra-yoga |
||
| let configs = borrow_global_mut<PendingConfigs>(@supra_framework); | ||
| let key = type_info::type_name<T>(); | ||
| let (_, value_packed) = simple_map::remove(&mut configs.configs, &key); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -894,6 +894,28 @@ module supra_framework::fungible_asset { | |
| let metadata_address = object::object_address(&metadata_ref.metadata); | ||
| let mutable_metadata = borrow_global_mut<Metadata>(metadata_address); | ||
|
|
||
| // Validate all provided values before mutating any metadata fields. | ||
| if (option::is_some(&name)){ | ||
| let new_name = option::borrow(&name); | ||
| assert!(string::length(new_name) <= MAX_NAME_LENGTH, error::out_of_range(ENAME_TOO_LONG)); | ||
| }; | ||
| if (option::is_some(&symbol)){ | ||
| let new_symbol = option::borrow(&symbol); | ||
| assert!(string::length(new_symbol) <= MAX_SYMBOL_LENGTH, error::out_of_range(ESYMBOL_TOO_LONG)); | ||
| }; | ||
| if (option::is_some(&decimals)){ | ||
| let new_decimals = option::borrow(&decimals); | ||
| assert!(*new_decimals <= MAX_DECIMALS, error::out_of_range(EDECIMALS_TOO_LARGE)); | ||
| }; | ||
| if (option::is_some(&icon_uri)){ | ||
| let new_icon_uri = option::borrow(&icon_uri); | ||
| assert!(string::length(new_icon_uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG)); | ||
| }; | ||
| if (option::is_some(&project_uri)){ | ||
| let new_project_uri = option::borrow(&project_uri); | ||
| assert!(string::length(new_project_uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG)); | ||
| }; | ||
|
|
||
|
Comment on lines
+897
to
+918
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than 2 conditional statement for a same cause Can we just update the values after the assert For example
Can we use
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In that case, if the 2nd or 3rd assertion fails, the 1st metadata would've been set incorrectly already. Therefore, checking for all the metadata limits before assigning them might be better, no? I am not sure how the Move compiler will process this flow. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @supra-yoga if one of the asserts gets failed then the txn will get failed so there wont be any partial state update There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @anshuman-supraoracles , @supra-yoga , Yes we can use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree, no need to perform
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Understood. Will update it as per the suggestion and also use |
||
| if (option::is_some(&name)){ | ||
| mutable_metadata.name = option::extract(&mut name); | ||
| }; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a breaking change to the execution semantics and needs to be feature gated. It would be simpler to update the docs to reflect the actual 1024 byte limit, if that is the only place that it is referenced. This will also avoid breaking any objects that have already been created in mainnet with a length between 256 and 1024 bytes. We need to check if any other code expects 256 bytes before doing this.