Description
Stop the live setter from writing a threshold the migration pre-flight is designed to reject.
Problem Statement
set_weight_threshold writes the caller's value straight to storage with no range check (src/contracts/proxy_entry/entry_config.rs:17-30):
crate::contracts::rbac::require_role(&env, &admin, crate::types::Role::ConfigManager)?;
env.storage().instance().set(&DataKey::WeightThreshold, &threshold);
validate_weight_threshold (src/validation.rs:84-92, rejecting 0 and > MAX_WEIGHT_THRESHOLD) exists and is invoked — but only by migrate::validate_migration at src/migrate.rs:169. So the live setter can write exactly the state the migration pre-flight rejects.
Verified: try_set_weight_threshold(&admin, &0) returns Ok(()) and get_weight_threshold() returns 0. A zero threshold makes consensus::apply_vote's total_weight_accrued >= threshold (src/consensus.rs:103) trivially true, so every task resolves on its first qualifying vote, silently defeating weighted consensus. It also poisons any future v1 → v2 migration: validate_migration would abort with InvalidAmount, leaving the contract unmigratable until the threshold is manually reset.
Proposed Changes
Technical Implementation Scaffolding
- Target Repository: vero-core-contracts
- Target Path: src/contracts/proxy_entry/entry_config.rs, src/validation.rs
- Branch Naming: fix/issue--validate-weight-threshold-setter
- Authority Context: Security-sensitive — consensus threshold; zero disables weighted voting
Acceptance Criteria
Definition of Done
Description
Stop the live setter from writing a threshold the migration pre-flight is designed to reject.
Problem Statement
set_weight_thresholdwrites the caller's value straight to storage with no range check (src/contracts/proxy_entry/entry_config.rs:17-30):validate_weight_threshold(src/validation.rs:84-92, rejecting0and> MAX_WEIGHT_THRESHOLD) exists and is invoked — but only bymigrate::validate_migrationatsrc/migrate.rs:169. So the live setter can write exactly the state the migration pre-flight rejects.Verified:
try_set_weight_threshold(&admin, &0)returnsOk(())andget_weight_threshold()returns0. A zero threshold makesconsensus::apply_vote'stotal_weight_accrued >= threshold(src/consensus.rs:103) trivially true, so every task resolves on its first qualifying vote, silently defeating weighted consensus. It also poisons any futurev1 → v2migration:validate_migrationwould abort withInvalidAmount, leaving the contract unmigratable until the threshold is manually reset.Proposed Changes
crate::validation::validate_weight_threshold(threshold)?inset_weight_thresholdbefore the storage write#[allow(dead_code)]onMAX_WEIGHT_THRESHOLD(src/limits.rs:50)InvalidAmount/InvalidRangein the entrypoint's error list, matching the style used onset_vault_addressTechnical Implementation Scaffolding
Acceptance Criteria
try_set_weight_threshold(admin, 0)returnsErr(ContractError::InvalidAmount)andget_weight_threshold()is unchangedtry_set_weight_threshold(admin, MAX_WEIGHT_THRESHOLD + 1)returnsErr(ContractError::InvalidRange)set_weight_thresholdis accepted bymigrate::validate_migration(property test over the accepted range)Definition of Done