From f5fd1a371e053f2d6be504808e718955e8b881f1 Mon Sep 17 00:00:00 2001 From: Reynaldo Gil Pons Date: Fri, 28 Aug 2026 10:10:03 +0200 Subject: [PATCH 1/2] fix(contract): use internal config::Config type instead of dto --- crates/contract/src/api/update.rs | 2 +- crates/contract/src/update.rs | 19 +++++++------------ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/crates/contract/src/api/update.rs b/crates/contract/src/api/update.rs index 9a57bfbe9..3e2d53a10 100644 --- a/crates/contract/src/api/update.rs +++ b/crates/contract/src/api/update.rs @@ -301,7 +301,7 @@ mod tests { let mut config_update = { let update_config = dummy_config(1); let config_hash = Sha256::digest(serde_json::to_vec(&update_config).unwrap()); - let config_update_obj = Update::Config(update_config.clone()); + let config_update_obj = Update::Config(update_config.try_into().unwrap()); let config_update_id = UpdateId(1); let config_votes = propose_and_vote(&mut contract, config_update_obj, config_update_id); TestUpdate { diff --git a/crates/contract/src/update.rs b/crates/contract/src/update.rs index fb4acc37e..6c472f076 100644 --- a/crates/contract/src/update.rs +++ b/crates/contract/src/update.rs @@ -2,6 +2,7 @@ use std::collections::BTreeMap; use std::hash::Hash; use crate::{ + config::Config, dto_mapping::IntoInterfaceType, errors::{ConversionError, Error}, primitives::participants::Participants, @@ -70,9 +71,9 @@ impl From for UpdateId { all(feature = "abi", not(target_arch = "wasm32")), derive(schemars::JsonSchema, borsh::BorshSchema) )] -pub enum Update { +pub(crate) enum Update { Contract(Vec), - Config(near_mpc_contract_interface::types::Config), + Config(Config), } impl TryFrom for Update { @@ -82,13 +83,7 @@ impl TryFrom for Update { let ProposeUpdateArgs { code, config } = value; let update = match (code, config) { (Some(contract), None) => Update::Contract(contract), - (None, Some(config)) => { - // Reject unusable configs at proposal time: `update_config` runs in its own - // receipt, so a validation failure at apply time cannot roll back `do_update` - // (which has already cleared the pending proposals in the caller's receipt). - let _: crate::config::Config = config.clone().try_into()?; - Update::Config(config) - } + (None, Some(config)) => Update::Config(config.try_into()?), (Some(_), Some(_)) => { return Err(ConversionError::DataConversion { reason: "Code and config updates are not allowed at the same time".into(), @@ -133,7 +128,7 @@ pub(super) struct UpdateVotes { #[near(serializers=[borsh ])] #[derive(Debug)] -pub struct ProposedUpdates { +pub(crate) struct ProposedUpdates { pub(super) vote_by_participant: IterableMap, pub(super) entries: IterableMap, pub(super) id: UpdateId, @@ -570,7 +565,7 @@ mod tests { let update_1 = Update::Contract([1; 1000].into()); let update_id_1 = proposed_updates.propose(update_1.clone()); - let update_2 = Update::Config(dummy_config(1)); + let update_2 = Update::Config(dummy_config(1).try_into().unwrap()); let update_id_2 = proposed_updates.propose(update_2.clone()); let account_0 = gen_account_id(); @@ -664,7 +659,7 @@ mod tests { let update_id_1 = proposed_updates.propose(update_1.clone()); assert_eq!(update_id_1.0, 1); - let update_2 = Update::Config(dummy_config(2)); + let update_2 = Update::Config(dummy_config(2).try_into().unwrap()); let update_id_2 = proposed_updates.propose(update_2.clone()); assert_eq!(update_id_2.0, 2); From 7dadb963ee166ccee74c3bb0d662488854cee188 Mon Sep 17 00:00:00 2001 From: Reynaldo Gil Pons Date: Fri, 28 Aug 2026 10:40:21 +0200 Subject: [PATCH 2/2] fix: address nits --- crates/contract/src/dto_mapping.rs | 36 +++++++++++++++++++++++++++++- crates/contract/src/update.rs | 3 ++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/crates/contract/src/dto_mapping.rs b/crates/contract/src/dto_mapping.rs index 632569318..a1840d9fb 100644 --- a/crates/contract/src/dto_mapping.rs +++ b/crates/contract/src/dto_mapping.rs @@ -432,12 +432,46 @@ impl IntoInterfaceType for &Update { match self { Update::Contract(code) => dtos::UpdateHash::Code(sha256_array(code)), Update::Config(config) => dtos::UpdateHash::Config(sha256_array( - serde_json::to_vec(config).expect("serde serialization must succeed"), + serde_json::to_vec(&config.into_dto_type()) + .expect("serde serialization must succeed"), )), } } } +impl IntoInterfaceType for &Config { + fn into_dto_type(self) -> dtos::Config { + dtos::Config { + key_event_timeout_blocks: self.key_event_timeout_blocks, + tee_upgrade_deadline_duration_seconds: self.tee_upgrade_deadline_duration_seconds, + contract_upgrade_deposit_tera_gas: self.contract_upgrade_deposit_tera_gas, + sign_call_gas_attachment_requirement_tera_gas: self + .sign_call_gas_attachment_requirement_tera_gas, + ckd_call_gas_attachment_requirement_tera_gas: self + .ckd_call_gas_attachment_requirement_tera_gas, + return_signature_and_clean_state_on_success_call_tera_gas: self + .return_signature_and_clean_state_on_success_call_tera_gas, + return_ck_and_clean_state_on_success_call_tera_gas: self + .return_ck_and_clean_state_on_success_call_tera_gas, + fail_on_timeout_tera_gas: self.fail_on_timeout_tera_gas, + fail_attestation_submission_tera_gas: self.fail_attestation_submission_tera_gas, + clean_tee_status_tera_gas: self.clean_tee_status_tera_gas, + clean_invalid_attestations_tera_gas: self.clean_invalid_attestations_tera_gas, + cleanup_orphaned_node_migrations_tera_gas: self + .cleanup_orphaned_node_migrations_tera_gas, + remove_non_participant_update_votes_tera_gas: self + .remove_non_participant_update_votes_tera_gas, + clean_foreign_chain_data_tera_gas: self.clean_foreign_chain_data_tera_gas, + remove_non_participant_tee_verifier_votes_tera_gas: self + .remove_non_participant_tee_verifier_votes_tera_gas, + verifier_tera_gas: self.verifier_tera_gas, + resolve_verification_tera_gas: self.resolve_verification_tera_gas, + launcher_hash_unused_ttl_seconds: self.launcher_hash_unused_ttl_seconds, + attestation_storage_fee_millinear: self.attestation_storage_fee_millinear, + } + } +} + impl IntoInterfaceType for &ProposedUpdates { fn into_dto_type(self) -> dtos::ProposedUpdates { let all = self.all_updates(); diff --git a/crates/contract/src/update.rs b/crates/contract/src/update.rs index 6c472f076..64bfe40e4 100644 --- a/crates/contract/src/update.rs +++ b/crates/contract/src/update.rs @@ -205,9 +205,10 @@ impl ProposedUpdates { // the value `contract_upgrade_deposit_tera_gas` from the config // as the new gas value let new_config_gas_value = Gas::from_tgas(config.contract_upgrade_deposit_tera_gas); + let dto_config = config.into_dto_type(); promise = promise.function_call( method_names::UPDATE_CONFIG, - serde_json::to_vec(&(&config,)).unwrap(), + serde_json::to_vec(&(&dto_config,)).unwrap(), NearToken::from_near(0), new_config_gas_value, );