feat(governance): RV16 — el override del veto se decide al cerrar la ventana, con 4/5 de quien participa
Cierra L-11 (override real del veto). David aprobó el 4/5 el 2026-10-01: «exigir una mayoría calificada de 4/5 en el consejo para anular un veto de emergencia es el cerrojo adecuado antes de retirar la llave Sudo». Qué cambia - La ventana de override tiene dos lados: revertir (override_council_veto) y sostener (uphold_council_veto, nuevo). Quien votó Nay puede sostener el veto; antes no tenía voz. - Nada se decide al cruzar un umbral. finalize_override (nuevo) decide UNA vez, al cerrar la ventana: se revierte si override >= ceil(4/5 * max(quórum, participación)). - El quórum se fija al vetar: max(Aye + Nay del voto original, MinOverrideQuorum). Abstain no cuenta. Así el bond que el veto devuelve no basta para revertirlo y un upgrade no lo mueve. - MinOverrideQuorum en el runtime = 100M OGC (el 10% de PILAR_4 §6.6); integrity_test exige que supere MIN_PROPOSAL_STAKE. - El periodo de voto ordinario dura al menos 14 días (MIN = DEFAULT) y el veto solo cabe dentro de él. Un voto de peso 0 en la ventana se rechaza. - spec_version 16. Pesos de uphold_council_veto y finalize_override medidos (frame-omni-bencher 0.15.0, 50 steps x 20 repeats); los demás re-medidos en el mismo banco. La revisión adversarial (nivel 1 de la directiva) tumbó la primera versión - Bloqueante: la regla de quórum no era monótona y votar «sostener» podía REVERTIR el veto. Ahora sostener nunca ayuda a revertir (test con la frontera exacta 2250/2251). - El mínimo de 48 h regalaba la vía de emergencia a cualquiera; ahora 14 días. - Las abstenciones inflaban el quórum; el quórum podía cambiar con un upgrade; la spec no subía. - 18 contrafactuales (mutaciones V1..V18), todos en rojo sin su pieza. Divergencia que queda abierta (D1 del roadmap V2): PILAR_4 §6.6 ratificó «override por 2/3» y el código implementa 4/5, que es lo que David confirmó. La constitución del DAO lo fija. Tests: gobernanza 78 (94 con runtime-benchmarks), runtime 44. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a694cbd9f0
commit
3771a15165
8 files changed
+1081
-173
No files matched your search
@@ -94,7 +94,13 @@ mod benchmarks {
|
||||
fund::<T>(&caller);
|
||||
|
||||
#[extrinsic_call]
|
||||
submit_proposal(RawOrigin::Signed(caller), [1u8; 32], [2u8; 32], 1_000u64, MIN_PROPOSAL_STAKE);
|
||||
submit_proposal(
|
||||
RawOrigin::Signed(caller),
|
||||
[1u8; 32],
|
||||
[2u8; 32],
|
||||
MIN_VOTING_PERIOD_BLOCKS,
|
||||
MIN_PROPOSAL_STAKE,
|
||||
);
|
||||
|
||||
assert_eq!(Proposals::<T>::iter().count(), 1);
|
||||
}
|
||||
@@ -230,7 +236,7 @@ mod benchmarks {
|
||||
seed_proposal::<T>(id, ProposalStatus::Rejected, 0u64);
|
||||
VetoRejected::<T>::insert(id, ());
|
||||
// RV15: ventana abierta, peso respaldado por saldo y la lista de respaldo casi
|
||||
// llena (peor caso). Y rama cara: el override ALCANZA el umbral y aprueba.
|
||||
// llena (peor caso). RV16: el voto ya no decide nada; eso es finalize_override.
|
||||
OverrideDeadline::<T>::insert(id, 1_000_000u64);
|
||||
fund::<T>(&caller);
|
||||
seed_backing::<T>(
|
||||
@@ -243,10 +249,6 @@ mod benchmarks {
|
||||
override_council_veto(RawOrigin::Signed(caller.clone()), id, MIN_PROPOSAL_STAKE);
|
||||
|
||||
assert!(OverrideVotes::<T>::contains_key(id, &caller));
|
||||
assert!(matches!(
|
||||
Proposals::<T>::get(id).unwrap().status,
|
||||
ProposalStatus::Approved
|
||||
));
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
@@ -332,5 +334,48 @@ mod benchmarks {
|
||||
assert_eq!(VoteLocks::<T>::get(&votante).len() as u32, max - vencidos);
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn uphold_council_veto() {
|
||||
// Mismo peor caso que override_council_veto, por el otro lado.
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
let id = ProposalId([7u8; 32]);
|
||||
seed_proposal::<T>(id, ProposalStatus::Rejected, 0u64);
|
||||
VetoRejected::<T>::insert(id, ());
|
||||
OverrideDeadline::<T>::insert(id, 1_000_000u64);
|
||||
fund::<T>(&caller);
|
||||
seed_backing::<T>(
|
||||
&caller,
|
||||
T::MaxActiveVotes::get().saturating_sub(1),
|
||||
1_000_000u64,
|
||||
);
|
||||
|
||||
#[extrinsic_call]
|
||||
uphold_council_veto(RawOrigin::Signed(caller.clone()), id, MIN_PROPOSAL_STAKE);
|
||||
|
||||
assert!(UpholdVotes::<T>::contains_key(id, &caller));
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn finalize_override() {
|
||||
// Rama cara: el override REVIERTE el veto (escribe la propuesta y el evento).
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
let id = ProposalId([7u8; 32]);
|
||||
seed_proposal::<T>(id, ProposalStatus::Rejected, 0u64);
|
||||
VetoRejected::<T>::insert(id, ());
|
||||
OverrideDeadline::<T>::insert(id, 1u64);
|
||||
OverrideQuorum::<T>::insert(id, T::MinOverrideQuorum::get());
|
||||
OverrideStakeTotal::<T>::insert(id, T::MinOverrideQuorum::get().max(1));
|
||||
frame_system::Pallet::<T>::set_block_number(2u32.into());
|
||||
|
||||
#[extrinsic_call]
|
||||
finalize_override(RawOrigin::Signed(caller), id);
|
||||
|
||||
assert!(matches!(
|
||||
Proposals::<T>::get(id).unwrap().status,
|
||||
ProposalStatus::Approved
|
||||
));
|
||||
assert!(!OverrideDeadline::<T>::contains_key(id));
|
||||
}
|
||||
|
||||
impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
|
||||
}
|
||||
@@ -23,7 +23,10 @@
|
||||
//! - 5.2: `pallet_collective` integration (Technical Council)
|
||||
//! - 5.3: OIP stake minimum 1,000 OGC canonical
|
||||
//! - 5.4: Stake-weighted voting (1 OGC = 1 vote, 14-day period)
|
||||
//! - 5.5: Technical Council veto + override (2/3 voters)
|
||||
//! - 5.5: Technical Council veto (2/3 del council) + override comunitario. PILAR_4 §6.6
|
||||
//! ratificó «overridable por 2/3 voters»; el código implementa 4/5 de la participación
|
||||
//! en la ventana, con quórum (RV16), y David confirmó el 4/5 el 2026-10-01. Lo que
|
||||
//! el código hace y lo que dice la doctrina difieren hasta que la constitución lo fije.
|
||||
//! - 5.6: AI governance agent interfaces (5 agents advise-only)
|
||||
//! - 5.7: Emergency referendum (48h, 5/7 Technical Council)
|
||||
//! - 5.8: Treasury disbursement extrinsics
|
||||
@@ -208,6 +211,17 @@ pub mod pallet {
|
||||
/// de quien votara en ella (demostrado por la revisión adversaria de RV15).
|
||||
pub const MAX_VOTING_PERIOD_BLOCKS: u64 = 2 * DEFAULT_VOTING_PERIOD_BLOCKS;
|
||||
|
||||
/// RV16: periodo de voto mínimo de una propuesta ORDINARIA: 14 días, el que
|
||||
/// ratifica PILAR_4 §6.6 («14-day period»).
|
||||
///
|
||||
/// Antes podía ser 0: el proponente enviaba, votaba en el mismo bloque y
|
||||
/// finalizaba en el siguiente, aprobando con su único voto. La primera versión de
|
||||
/// RV16 lo subió a 48 h y la revisión adversaria mostró por qué no basta: era la
|
||||
/// duración de la vía de emergencia sin sus 5/7 endosos del council, y como el
|
||||
/// veto solo cabe dentro del periodo, el proponente elegía cuánto tiempo tenía el
|
||||
/// council para reaccionar. Las 48 h quedan solo para `submit_emergency_proposal`.
|
||||
pub const MIN_VOTING_PERIOD_BLOCKS: u64 = DEFAULT_VOTING_PERIOD_BLOCKS;
|
||||
|
||||
/// Emergency voting period canonical canonical 48 hours per CHN-4 5.7.
|
||||
/// 48 hours × 600 blocks/hour (@ 6s slot Aura) = 28,800 blocks.
|
||||
pub const EMERGENCY_VOTING_PERIOD_BLOCKS: u64 = 48 * 600;
|
||||
@@ -309,6 +323,14 @@ pub mod pallet {
|
||||
#[pallet::constant]
|
||||
type MaxActiveVotes: Get<u32>;
|
||||
|
||||
/// RV16: participación mínima (en OGC) para que un override pueda revertir
|
||||
/// un veto. El quórum efectivo, fijado en el veto, es el MAYOR entre esto y la
|
||||
/// participación del voto original (Aye + Nay): revertir al council exige al
|
||||
/// menos tanta comunidad como la que votó. Es un parámetro de la constitución,
|
||||
/// y `integrity_test` exige que supere el bond de una propuesta.
|
||||
#[pallet::constant]
|
||||
type MinOverrideQuorum: Get<u128>;
|
||||
|
||||
/// FIX-6: PalletId del que se deriva la cuenta-tesorería (vault). Cuenta
|
||||
/// determinística sin private key — nadie la controla por wallet, solo la
|
||||
/// governance vía treasury_disbursement (Root). Honor Inmutable #16: la
|
||||
@@ -330,6 +352,19 @@ pub mod pallet {
|
||||
#[pallet::storage_version(STORAGE_VERSION)]
|
||||
pub struct Pallet<T>(_);
|
||||
|
||||
#[pallet::hooks]
|
||||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
|
||||
/// RV16: el quórum de override tiene que superar el bond de una propuesta. Si
|
||||
/// no, el proponente revertiría solo el veto con el bond que el propio veto le
|
||||
/// devuelve (hallazgo C3), y con 0 bastaría una unidad base.
|
||||
fn integrity_test() {
|
||||
assert!(
|
||||
T::MinOverrideQuorum::get() > MIN_PROPOSAL_STAKE,
|
||||
"MinOverrideQuorum debe superar MIN_PROPOSAL_STAKE (hallazgo C3)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// RV15: por qué este pallet congela OGC.
|
||||
#[pallet::composite_enum]
|
||||
pub enum FreezeReason {
|
||||
@@ -339,6 +374,25 @@ pub mod pallet {
|
||||
GovernanceVote,
|
||||
}
|
||||
|
||||
/// RV16: votos que SOSTIENEN el veto del council durante su ventana de
|
||||
/// override (la otra mitad del recuento; antes no existía y quien votó Nay no
|
||||
/// podía defender el veto).
|
||||
#[pallet::storage]
|
||||
pub type UpholdVotes<T: Config> = StorageDoubleMap<
|
||||
_,
|
||||
Blake2_128Concat,
|
||||
ProposalId,
|
||||
Blake2_128Concat,
|
||||
T::AccountId,
|
||||
u128,
|
||||
OptionQuery,
|
||||
>;
|
||||
|
||||
/// RV16: OGC total que sostiene el veto, por propuesta.
|
||||
#[pallet::storage]
|
||||
pub type UpholdStakeTotal<T: Config> =
|
||||
StorageMap<_, Blake2_128Concat, ProposalId, u128, ValueQuery>;
|
||||
|
||||
/// RV15: los votos vivos que respalda cada cuenta (ver [`VoteBacking`]). El
|
||||
/// freeze `GovernanceVote` de la cuenta es el máximo de sus `amount`.
|
||||
#[pallet::storage]
|
||||
@@ -357,6 +411,16 @@ pub mod pallet {
|
||||
pub type OverrideDeadline<T: Config> =
|
||||
StorageMap<_, Blake2_128Concat, ProposalId, u64, OptionQuery>;
|
||||
|
||||
/// RV16: quórum del override de cada propuesta vetada, FIJADO en el veto:
|
||||
/// max(Aye + Nay del voto original, `MinOverrideQuorum`). Se guarda y no se
|
||||
/// recalcula al decidir: un runtime upgrade que cambie el parámetro no mueve la
|
||||
/// meta de una ventana ya abierta (hallazgo de la revisión de RV16). La
|
||||
/// abstención no cuenta: si contara, el mismo OGC abstenido en muchas propuestas
|
||||
/// a la vez inflaría el quórum de todas sin aparecer en ninguna ventana.
|
||||
#[pallet::storage]
|
||||
pub type OverrideQuorum<T: Config> =
|
||||
StorageMap<_, Blake2_128Concat, ProposalId, u128, OptionQuery>;
|
||||
|
||||
/// CHN-4 canonical: `Proposals<StorageMap<ProposalId, Proposal>>` canonical.
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn proposal_of)]
|
||||
@@ -595,15 +659,16 @@ pub mod pallet {
|
||||
},
|
||||
/// Council veto canonical overridden por community supermajority (Phase 5.5 v0.0.35).
|
||||
///
|
||||
/// Emitted canonical cuando override votes reach 4/5 total stake canonical canonical.
|
||||
/// Proposal status canonical flipped from Rejected back to Voting OR Approved
|
||||
/// (depending canonical en tally pre-veto).
|
||||
/// RV16: lo emite `finalize_override` cuando, cerrada la ventana, revertir
|
||||
/// reunió 4/5 del mayor entre el quórum y la participación. La propuesta pasa
|
||||
/// a `Approved`. (Antes se emitía al cruzar el umbral en mitad de la ventana.)
|
||||
CouncilVetoOverridden {
|
||||
/// ProposalId canonical overridden.
|
||||
/// Propuesta cuyo veto se revierte.
|
||||
id: ProposalId,
|
||||
/// Total override stake canonical at moment of override.
|
||||
/// OGC que votó revertir.
|
||||
override_stake: u128,
|
||||
/// Total community stake canonical baseline (proposal.stake at submit).
|
||||
/// RV16: participación total en la ventana (revertir + sostener). Antes era
|
||||
/// la base del umbral viejo (stake + yes + nay + abstain de la propuesta).
|
||||
total_community_stake: u128,
|
||||
},
|
||||
/// Emergency proposal submitted canonical (Phase 5.7 v0.0.35).
|
||||
@@ -654,6 +719,30 @@ pub mod pallet {
|
||||
/// OGC que sigue congelado por votos todavía vivos.
|
||||
still_frozen: u128,
|
||||
},
|
||||
/// RV16: un voto en la ventana de override de un veto (para el indexer del
|
||||
/// portal: antes un voto de override no emitía nada hasta el desenlace).
|
||||
OverrideVoteCast {
|
||||
/// Propuesta vetada.
|
||||
id: ProposalId,
|
||||
/// Quien vota.
|
||||
voter: T::AccountId,
|
||||
/// `true` = sostiene el veto; `false` = vota revertirlo.
|
||||
uphold: bool,
|
||||
/// OGC que respalda el voto (congelado hasta el cierre de la ventana).
|
||||
weight: u128,
|
||||
},
|
||||
/// RV16: se cerró la ventana y el veto se SOSTIENE (el override no alcanzó
|
||||
/// 4/5 de la participación o no hubo quórum).
|
||||
CouncilVetoUpheld {
|
||||
/// Propuesta vetada.
|
||||
id: ProposalId,
|
||||
/// OGC que votó revertir el veto.
|
||||
override_stake: u128,
|
||||
/// OGC que votó sostenerlo.
|
||||
uphold_stake: u128,
|
||||
/// Quórum que se exigía.
|
||||
quorum: u128,
|
||||
},
|
||||
}
|
||||
|
||||
/// Pallet errors canonical.
|
||||
@@ -729,6 +818,15 @@ pub mod pallet {
|
||||
VotingPeriodTooLong,
|
||||
/// RV15: la cuenta ya respalda `MaxActiveVotes` votos vivos.
|
||||
TooManyActiveVotes,
|
||||
/// RV16: el periodo de voto pedido es menor que `MIN_VOTING_PERIOD_BLOCKS`.
|
||||
VotingPeriodTooShort,
|
||||
/// RV16: la ventana de override sigue abierta; el resultado se decide al
|
||||
/// cerrarse, no al cruzar un umbral a mitad de camino.
|
||||
OverrideWindowOpen,
|
||||
/// RV16: esta propuesta no tiene un override pendiente de decidir.
|
||||
OverrideNotPending,
|
||||
/// RV16: un voto de la ventana de override tiene que pesar más de 0.
|
||||
ZeroWeightWindowVote,
|
||||
}
|
||||
|
||||
/// Minimum stake canonical proposal submission per CHN-4 5.3.
|
||||
@@ -763,6 +861,10 @@ pub mod pallet {
|
||||
voting_period_blocks <= MAX_VOTING_PERIOD_BLOCKS,
|
||||
Error::<T>::VotingPeriodTooLong
|
||||
);
|
||||
ensure!(
|
||||
voting_period_blocks >= MIN_VOTING_PERIOD_BLOCKS,
|
||||
Error::<T>::VotingPeriodTooShort
|
||||
);
|
||||
|
||||
let proposer_acct = AccountId::new(account_bytes::<T>(&who));
|
||||
let id = crate::derive_proposal_id(&proposer_acct, &title_hash, &body_hash);
|
||||
@@ -1044,6 +1146,14 @@ pub mod pallet {
|
||||
Error::<T>::ProposalAlreadyFinalized
|
||||
);
|
||||
|
||||
// RV16: el veto solo cabe DURANTE el periodo de voto. Antes se podía vetar
|
||||
// entre end_block y el finalize, y el resultado dependía de quién llamara
|
||||
// primero (carrera entre el council y cualquiera que finalizara).
|
||||
ensure!(
|
||||
current_block_u64::<T>() <= proposal.end_block,
|
||||
Error::<T>::VotingPeriodClosed
|
||||
);
|
||||
|
||||
// Step 4: council size canonical > 0
|
||||
let council_size = CouncilSize::<T>::get();
|
||||
ensure!(council_size > 0, Error::<T>::InsufficientCouncilSize);
|
||||
@@ -1070,6 +1180,10 @@ pub mod pallet {
|
||||
|
||||
let required = council_veto_threshold(council_size);
|
||||
if live_count >= required {
|
||||
// RV16: el quórum del override se fija AQUÍ, con la participación del
|
||||
// voto original (Aye + Nay; la abstención no cuenta).
|
||||
let turnout = proposal.yes_weight.saturating_add(proposal.nay_weight);
|
||||
OverrideQuorum::<T>::insert(proposal_id, turnout.max(T::MinOverrideQuorum::get()));
|
||||
// Veto threshold reached canonical → flip status canonical
|
||||
proposal.status = ProposalStatus::Rejected;
|
||||
Proposals::<T>::insert(proposal_id, proposal);
|
||||
@@ -1142,21 +1256,21 @@ pub mod pallet {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// CHN-4 5.5 v0.0.35 canonical: `override_council_veto` Phase 5.5 dispatchable.
|
||||
/// CHN-4 5.5 + RV16: votar REVERTIR un veto del council durante su ventana.
|
||||
///
|
||||
/// Community supermajority canonical override de council veto. 4/5 total stake
|
||||
/// canonical required canonical per CHN-4 5.5. Proposal status canonical flipped
|
||||
/// desde Rejected canonical back to Approved canonical (community canonical >
|
||||
/// council canonical veto on supermajority).
|
||||
/// Doctrina: el council veta con 2/3 y la comunidad revierte con 4/5
|
||||
/// (`docs/ORIGIN_DAO_DONDE_VIVE_V1.md`). RV16 hace real ese 4/5 (hallazgo C3 de
|
||||
/// SUPER_AUDIT_V1, demostrado otra vez por la revisión de RV15):
|
||||
/// - el voto NO voltea nada al cruzar un umbral; el resultado se decide al
|
||||
/// cerrarse la ventana, en [`Pallet::finalize_override`];
|
||||
/// - el 4/5 es de la PARTICIPACIÓN en la ventana (revertir + sostener), no de
|
||||
/// los recuentos de la propia propuesta: antes contaba el bond del proponente,
|
||||
/// que el veto le devuelve y que luego podía votar;
|
||||
/// - quien quiere el veto puede defenderlo con [`Pallet::uphold_council_veto`];
|
||||
/// - hace falta quórum.
|
||||
///
|
||||
/// 7-step canonical flow:
|
||||
/// 1. ensure_signed canonical
|
||||
/// 2. Get proposal (must canonical be Rejected previamente vía veto)
|
||||
/// 3. Validate proposal.stake > 0 (baseline canonical)
|
||||
/// 4. !AdvisorFlags canonical (humans-only canonical canonical)
|
||||
/// 5. !OverrideVotes contains canonical (double-vote prevention)
|
||||
/// 6. Insert vote + increment total stake
|
||||
/// 7. Check threshold canonical 4/5: if >= → flip to Approved + emit CouncilVetoOverridden
|
||||
/// El peso sale del saldo y queda congelado hasta el cierre de la ventana (RV15).
|
||||
/// Una cuenta vota una vez en la ventana, en un solo lado.
|
||||
#[pallet::call_index(8)]
|
||||
#[pallet::weight(T::WeightInfo::override_council_veto())]
|
||||
pub fn override_council_veto(
|
||||
@@ -1165,73 +1279,7 @@ pub mod pallet {
|
||||
stake_weight: u128,
|
||||
) -> DispatchResult {
|
||||
let who = ensure_signed(origin)?;
|
||||
|
||||
let mut proposal = Proposals::<T>::get(proposal_id)
|
||||
.ok_or(Error::<T>::ProposalNotFound)?;
|
||||
|
||||
ensure!(
|
||||
matches!(proposal.status, ProposalStatus::Rejected),
|
||||
Error::<T>::ProposalNotRejected
|
||||
);
|
||||
|
||||
// Audit 2026-07-04: el override SOLO revierte un VETO del council, no
|
||||
// un rechazo por voto popular. Sin esta marca, una propuesta que la
|
||||
// comunidad votó EN CONTRA (Rejected vía finalize_proposal) podía
|
||||
// resucitarse a Approved, invirtiendo el voto. Solo las vetadas aplican.
|
||||
ensure!(
|
||||
VetoRejected::<T>::contains_key(proposal_id),
|
||||
Error::<T>::ProposalNotVetoRejected
|
||||
);
|
||||
|
||||
ensure!(
|
||||
!AdvisorFlags::<T>::contains_key(&who),
|
||||
Error::<T>::AdvisorMayNotVote
|
||||
);
|
||||
|
||||
ensure!(
|
||||
!OverrideVotes::<T>::contains_key(proposal_id, &who),
|
||||
Error::<T>::AlreadyOverrideVoted
|
||||
);
|
||||
|
||||
// RV15: el override tiene ventana, y su peso sale del saldo y queda
|
||||
// congelado hasta que la ventana cierre.
|
||||
let deadline =
|
||||
OverrideDeadline::<T>::get(proposal_id).ok_or(Error::<T>::OverrideWindowClosed)?;
|
||||
ensure!(
|
||||
current_block_u64::<T>() <= deadline,
|
||||
Error::<T>::OverrideWindowClosed
|
||||
);
|
||||
Self::back_vote_with_funds(
|
||||
&who,
|
||||
proposal_id,
|
||||
BackingKind::Override,
|
||||
stake_weight,
|
||||
deadline,
|
||||
)?;
|
||||
|
||||
OverrideVotes::<T>::insert(proposal_id, &who, stake_weight);
|
||||
let new_total = OverrideStakeTotal::<T>::get(proposal_id)
|
||||
.saturating_add(stake_weight);
|
||||
OverrideStakeTotal::<T>::insert(proposal_id, new_total);
|
||||
|
||||
let baseline = proposal.stake.saturating_add(proposal.yes_weight)
|
||||
.saturating_add(proposal.nay_weight)
|
||||
.saturating_add(proposal.abstain_weight);
|
||||
|
||||
let required = override_supermajority_threshold(baseline);
|
||||
|
||||
if new_total >= required {
|
||||
proposal.status = ProposalStatus::Approved;
|
||||
Proposals::<T>::insert(proposal_id, proposal);
|
||||
|
||||
Self::deposit_event(Event::CouncilVetoOverridden {
|
||||
id: proposal_id,
|
||||
override_stake: new_total,
|
||||
total_community_stake: baseline,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Self::cast_override_window_vote(who, proposal_id, stake_weight, false)
|
||||
}
|
||||
|
||||
/// CHN-4 5.7 v0.0.35 canonical: `submit_emergency_proposal` Phase 5.7 dispatchable.
|
||||
@@ -1473,6 +1521,89 @@ pub mod pallet {
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// RV16: votar SOSTENER un veto del council durante su ventana de override.
|
||||
/// Es la otra mitad del recuento: sin ella, quien votó Nay no podía defender
|
||||
/// el veto y cualquier minoría con OGC suficiente lo revertía sola.
|
||||
#[pallet::call_index(14)]
|
||||
#[pallet::weight(T::WeightInfo::uphold_council_veto())]
|
||||
pub fn uphold_council_veto(
|
||||
origin: OriginFor<T>,
|
||||
proposal_id: ProposalId,
|
||||
stake_weight: u128,
|
||||
) -> DispatchResult {
|
||||
let who = ensure_signed(origin)?;
|
||||
Self::cast_override_window_vote(who, proposal_id, stake_weight, true)
|
||||
}
|
||||
|
||||
/// RV16: decide un override cuando su ventana ya cerró. Lo puede llamar
|
||||
/// cualquiera.
|
||||
///
|
||||
/// El veto se revierte (la propuesta pasa a `Approved`) solo si:
|
||||
/// 1. la participación (revertir + sostener) alcanza el quórum, que es el
|
||||
/// MAYOR entre `MinOverrideQuorum` y la participación del voto original
|
||||
/// (Aye + Nay + Abstain); y
|
||||
/// 2. revertir reúne al menos 4/5 de esa participación.
|
||||
///
|
||||
/// En cualquier otro caso el veto se sostiene. Se decide una sola vez.
|
||||
#[pallet::call_index(15)]
|
||||
#[pallet::weight(T::WeightInfo::finalize_override())]
|
||||
pub fn finalize_override(origin: OriginFor<T>, proposal_id: ProposalId) -> DispatchResult {
|
||||
ensure_signed(origin)?;
|
||||
let mut proposal =
|
||||
Proposals::<T>::get(proposal_id).ok_or(Error::<T>::ProposalNotFound)?;
|
||||
ensure!(
|
||||
matches!(proposal.status, ProposalStatus::Rejected),
|
||||
Error::<T>::ProposalNotRejected
|
||||
);
|
||||
ensure!(
|
||||
VetoRejected::<T>::contains_key(proposal_id),
|
||||
Error::<T>::ProposalNotVetoRejected
|
||||
);
|
||||
let deadline =
|
||||
OverrideDeadline::<T>::get(proposal_id).ok_or(Error::<T>::OverrideNotPending)?;
|
||||
ensure!(
|
||||
current_block_u64::<T>() > deadline,
|
||||
Error::<T>::OverrideWindowOpen
|
||||
);
|
||||
|
||||
let override_stake = OverrideStakeTotal::<T>::get(proposal_id);
|
||||
let uphold_stake = UpholdStakeTotal::<T>::get(proposal_id);
|
||||
let participation = override_stake.saturating_add(uphold_stake);
|
||||
let quorum =
|
||||
OverrideQuorum::<T>::get(proposal_id).ok_or(Error::<T>::OverrideNotPending)?;
|
||||
|
||||
// Se decide una sola vez: sin ventana, no hay override pendiente.
|
||||
OverrideDeadline::<T>::remove(proposal_id);
|
||||
OverrideQuorum::<T>::remove(proposal_id);
|
||||
|
||||
// Regla MONÓTONA: revertir necesita 4/5 del MAYOR entre el quórum y la
|
||||
// participación. La primera versión exigía `participation >= quorum` y
|
||||
// aparte el 4/5 de la participación, y la revisión adversaria demostró que
|
||||
// así SOSTENER podía revertir el veto: un voto de sostener completaba el
|
||||
// quórum que el lado revertir no alcanzaba solo, y no votar era la manera
|
||||
// de defender el veto. Con max(quorum, participación), cada OGC que sostiene
|
||||
// solo puede subir el listón de revertir, nunca bajarlo.
|
||||
let overridden = override_stake > 0
|
||||
&& override_stake >= override_supermajority_threshold(quorum.max(participation));
|
||||
if overridden {
|
||||
proposal.status = ProposalStatus::Approved;
|
||||
Proposals::<T>::insert(proposal_id, proposal);
|
||||
Self::deposit_event(Event::CouncilVetoOverridden {
|
||||
id: proposal_id,
|
||||
override_stake,
|
||||
total_community_stake: participation,
|
||||
});
|
||||
} else {
|
||||
Self::deposit_event(Event::CouncilVetoUpheld {
|
||||
id: proposal_id,
|
||||
override_stake,
|
||||
uphold_stake,
|
||||
quorum,
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// El mayor OGC respaldado por una lista de votos (0 si está vacía).
|
||||
@@ -1485,6 +1616,74 @@ pub mod pallet {
|
||||
<frame_system::Pallet<T>>::block_number().saturated_into::<u64>()
|
||||
}
|
||||
|
||||
/// RV16 — un voto en la ventana de override de un veto, de cualquiera de los dos
|
||||
/// lados. Comparte TODAS las comprobaciones: que la propuesta esté vetada (no
|
||||
/// rechazada por voto popular), que la ventana esté abierta, que la cuenta no sea
|
||||
/// advisor, que no haya votado ya en la ventana (en ningún lado), y que el peso
|
||||
/// salga de su saldo y quede congelado hasta el cierre.
|
||||
impl<T: Config> Pallet<T> {
|
||||
fn cast_override_window_vote(
|
||||
who: T::AccountId,
|
||||
proposal_id: ProposalId,
|
||||
stake_weight: u128,
|
||||
uphold: bool,
|
||||
) -> DispatchResult {
|
||||
// Un voto de peso 0 en la ventana no decide nada y dejaría una entrada
|
||||
// permanente (y a la cuenta sin poder votar después en esa ventana).
|
||||
ensure!(stake_weight > 0, Error::<T>::ZeroWeightWindowVote);
|
||||
let proposal = Proposals::<T>::get(proposal_id).ok_or(Error::<T>::ProposalNotFound)?;
|
||||
ensure!(
|
||||
matches!(proposal.status, ProposalStatus::Rejected),
|
||||
Error::<T>::ProposalNotRejected
|
||||
);
|
||||
// Audit 2026-07-04: el override SOLO revierte un VETO del council, no
|
||||
// un rechazo por voto popular.
|
||||
ensure!(
|
||||
VetoRejected::<T>::contains_key(proposal_id),
|
||||
Error::<T>::ProposalNotVetoRejected
|
||||
);
|
||||
ensure!(
|
||||
!AdvisorFlags::<T>::contains_key(&who),
|
||||
Error::<T>::AdvisorMayNotVote
|
||||
);
|
||||
ensure!(
|
||||
!OverrideVotes::<T>::contains_key(proposal_id, &who)
|
||||
&& !UpholdVotes::<T>::contains_key(proposal_id, &who),
|
||||
Error::<T>::AlreadyOverrideVoted
|
||||
);
|
||||
let deadline =
|
||||
OverrideDeadline::<T>::get(proposal_id).ok_or(Error::<T>::OverrideWindowClosed)?;
|
||||
ensure!(
|
||||
current_block_u64::<T>() <= deadline,
|
||||
Error::<T>::OverrideWindowClosed
|
||||
);
|
||||
Self::back_vote_with_funds(
|
||||
&who,
|
||||
proposal_id,
|
||||
BackingKind::Override,
|
||||
stake_weight,
|
||||
deadline,
|
||||
)?;
|
||||
|
||||
if uphold {
|
||||
UpholdVotes::<T>::insert(proposal_id, &who, stake_weight);
|
||||
UpholdStakeTotal::<T>::mutate(proposal_id, |t| *t = t.saturating_add(stake_weight));
|
||||
} else {
|
||||
OverrideVotes::<T>::insert(proposal_id, &who, stake_weight);
|
||||
OverrideStakeTotal::<T>::mutate(proposal_id, |t| {
|
||||
*t = t.saturating_add(stake_weight)
|
||||
});
|
||||
}
|
||||
Self::deposit_event(Event::OverrideVoteCast {
|
||||
id: proposal_id,
|
||||
voter: who,
|
||||
uphold,
|
||||
weight: stake_weight,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// RV15 — el OGC que respalda un voto.
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Exige que `weight` no supere el OGC LIBRE de `who` y lo deja congelado
|
||||
|
||||
@@ -48,6 +48,11 @@ impl origin_chain_governance::Config for Test {
|
||||
type RuntimeFreezeReason = RuntimeFreezeReason;
|
||||
// Bajo a propósito: el límite de votos vivos tiene que poder probarse.
|
||||
type MaxActiveVotes = frame_support::traits::ConstU32<4>;
|
||||
// RV16: quórum mínimo de override del mock = DOS bonds (2.000 OGC). Por encima del
|
||||
// bond a propósito, como en el runtime (100M OGC frente a 1.000): con el quórum
|
||||
// igual al bond, el proponente revertía solo con el bond devuelto (revisión de RV16).
|
||||
type MinOverrideQuorum =
|
||||
frame_support::traits::ConstU128<{ 2 * crate::pallet::MIN_PROPOSAL_STAKE }>;
|
||||
type TreasuryPalletId = TestTreasuryPalletId;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
@@ -27,7 +27,13 @@ use origin_chain_types::{AccountId, VoteStance};
|
||||
|
||||
const TITLE_HASH: [u8; 32] = [10u8; 32];
|
||||
const BODY_HASH: [u8; 32] = [20u8; 32];
|
||||
const VOTING_PERIOD: u64 = 100;
|
||||
/// RV16: el periodo de los tests es el mínimo legal (48 h). Antes era 100 bloques,
|
||||
/// que hoy rechaza `submit_proposal`.
|
||||
const VOTING_PERIOD: u64 = crate::pallet::MIN_VOTING_PERIOD_BLOCKS;
|
||||
/// Un bloque claramente posterior al fin del periodo de `submit_default` (inicio
|
||||
/// en el bloque 1). Sustituye a los `run_to_block(200)` que suponían un periodo
|
||||
/// de 100 bloques.
|
||||
const TRAS_EL_PERIODO: u64 = 1 + VOTING_PERIOD + 100;
|
||||
|
||||
fn submit_default(origin: frame_system::pallet_prelude::OriginFor<Test>) -> ProposalId {
|
||||
let alice_bytes = alice_account_bytes();
|
||||
@@ -187,7 +193,7 @@ fn scenario_7_finalize_approved_yes_majority_canonical() {
|
||||
assert_ok!(Governance::cast_vote(charlie_origin(), id, VoteStance::Nay, 500));
|
||||
|
||||
// Advance past voting period
|
||||
run_to_block(200);
|
||||
run_to_block(TRAS_EL_PERIODO);
|
||||
|
||||
assert_ok!(Governance::finalize_proposal(alice_origin(), id));
|
||||
|
||||
@@ -214,7 +220,7 @@ fn scenario_8_finalize_rejected_nay_majority_canonical() {
|
||||
assert_ok!(Governance::cast_vote(bob_origin(), id, VoteStance::Aye, 300));
|
||||
assert_ok!(Governance::cast_vote(charlie_origin(), id, VoteStance::Nay, 700));
|
||||
|
||||
run_to_block(200);
|
||||
run_to_block(TRAS_EL_PERIODO);
|
||||
|
||||
assert_ok!(Governance::finalize_proposal(alice_origin(), id));
|
||||
|
||||
@@ -239,7 +245,7 @@ fn scenario_8b_finalize_tie_rejected_canonical() {
|
||||
assert_ok!(Governance::cast_vote(bob_origin(), id, VoteStance::Aye, 500));
|
||||
assert_ok!(Governance::cast_vote(charlie_origin(), id, VoteStance::Nay, 500));
|
||||
|
||||
run_to_block(200);
|
||||
run_to_block(TRAS_EL_PERIODO);
|
||||
|
||||
assert_ok!(Governance::finalize_proposal(alice_origin(), id));
|
||||
|
||||
@@ -262,7 +268,7 @@ fn scenario_9_vote_closed_period_rejected_canonical() {
|
||||
let id = submit_default(alice_origin());
|
||||
|
||||
// Advance past voting period
|
||||
run_to_block(200);
|
||||
run_to_block(TRAS_EL_PERIODO);
|
||||
|
||||
// Vote after end_block → VotingPeriodClosed
|
||||
assert_noop!(
|
||||
@@ -650,21 +656,29 @@ fn override_scenario_2_successful_override_canonical() {
|
||||
let proposal = Proposals::<Test>::get(id).unwrap();
|
||||
assert!(matches!(proposal.status, ProposalStatus::Rejected));
|
||||
|
||||
// Community supermajority override canonical
|
||||
// baseline = stake + yes + nay + abstain = MIN_PROPOSAL_STAKE (no votes cast)
|
||||
// required = ceil(baseline × 4 / 5)
|
||||
let baseline = MIN_PROPOSAL_STAKE;
|
||||
let required = (baseline * 4 + 4) / 5;
|
||||
|
||||
// Bob casts override con stake = required (enough)
|
||||
// RV16: Bob vota revertir con el quórum mínimo (sin votos previos, el quórum
|
||||
// es MinOverrideQuorum = 2 × MIN_PROPOSAL_STAKE en el mock) y nadie sostiene.
|
||||
assert_ok!(Governance::override_council_veto(
|
||||
bob_origin(),
|
||||
id,
|
||||
required,
|
||||
2 * MIN_PROPOSAL_STAKE,
|
||||
));
|
||||
// El voto no voltea nada: el resultado se decide al cerrar la ventana.
|
||||
assert!(matches!(
|
||||
Proposals::<Test>::get(id).unwrap().status,
|
||||
ProposalStatus::Rejected
|
||||
));
|
||||
let cierre = crate::OverrideDeadline::<Test>::get(id).expect("ventana");
|
||||
run_to_block(cierre + 1);
|
||||
assert_ok!(Governance::finalize_override(charlie_origin(), id));
|
||||
|
||||
let proposal_after = Proposals::<Test>::get(id).unwrap();
|
||||
assert!(matches!(proposal_after.status, ProposalStatus::Approved));
|
||||
System::assert_last_event(RuntimeEvent::Governance(Event::CouncilVetoOverridden {
|
||||
id,
|
||||
override_stake: 2 * MIN_PROPOSAL_STAKE,
|
||||
total_community_stake: 2 * MIN_PROPOSAL_STAKE,
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -881,7 +895,7 @@ fn treasury_scenario_3_insufficient_balance_rejected_canonical() {
|
||||
// Setup approved proposal
|
||||
let id = submit_default(alice_origin());
|
||||
assert_ok!(Governance::cast_vote(bob_origin(), id, VoteStance::Aye, 1000));
|
||||
run_to_block(200);
|
||||
run_to_block(TRAS_EL_PERIODO);
|
||||
assert_ok!(Governance::finalize_proposal(alice_origin(), id));
|
||||
|
||||
// Try disburse 200 (exceeds 100 balance)
|
||||
@@ -908,7 +922,7 @@ fn treasury_scenario_4_successful_disbursement_canonical() {
|
||||
// Setup approved proposal
|
||||
let id = submit_default(alice_origin());
|
||||
assert_ok!(Governance::cast_vote(bob_origin(), id, VoteStance::Aye, 1000));
|
||||
run_to_block(200);
|
||||
run_to_block(TRAS_EL_PERIODO);
|
||||
assert_ok!(Governance::finalize_proposal(alice_origin(), id));
|
||||
|
||||
// Disburse 300_000 canonical
|
||||
@@ -951,7 +965,7 @@ fn override_no_puede_revertir_un_rechazo_por_voto_popular() {
|
||||
// La comunidad la rechaza en las urnas (Nay > Aye).
|
||||
assert_ok!(Governance::cast_vote(bob_origin(), id, VoteStance::Aye, 100));
|
||||
assert_ok!(Governance::cast_vote(charlie_origin(), id, VoteStance::Nay, 900));
|
||||
run_to_block(200);
|
||||
run_to_block(TRAS_EL_PERIODO);
|
||||
assert_ok!(Governance::finalize_proposal(alice_origin(), id));
|
||||
let p = Proposals::<Test>::get(id).unwrap();
|
||||
assert!(matches!(p.status, ProposalStatus::Rejected), "rechazada por voto");
|
||||
@@ -977,7 +991,7 @@ fn treasury_disbursement_es_single_use_anti_replay() {
|
||||
assert_ok!(Governance::treasury_deposit(alice_origin(), 1_000_000));
|
||||
let id = submit_default(alice_origin());
|
||||
assert_ok!(Governance::cast_vote(bob_origin(), id, VoteStance::Aye, 1000));
|
||||
run_to_block(200);
|
||||
run_to_block(TRAS_EL_PERIODO);
|
||||
assert_ok!(Governance::finalize_proposal(alice_origin(), id));
|
||||
|
||||
// Primer desembolso: OK.
|
||||
@@ -1054,7 +1068,7 @@ fn bond_se_retiene_al_someter_y_se_devuelve_al_finalizar() {
|
||||
assert_eq!(bal(&alice_account()), before - MIN_PROPOSAL_STAKE, "bond retenido");
|
||||
assert_eq!(bal(&bond_acct), MIN_PROPOSAL_STAKE, "og/props tiene el bond");
|
||||
// Finaliza (sin votos → Rejected) → bond devuelto íntegro.
|
||||
run_to_block(200);
|
||||
run_to_block(TRAS_EL_PERIODO);
|
||||
assert_ok!(Governance::finalize_proposal(alice_origin(), id));
|
||||
assert_eq!(bal(&alice_account()), before, "bond devuelto al finalizar");
|
||||
assert_eq!(bal(&bond_acct), 0, "cuenta-bond vacía");
|
||||
@@ -1090,7 +1104,13 @@ fn submit_rechazado_si_no_alcanza_para_el_bond() {
|
||||
)
|
||||
.into();
|
||||
assert_noop!(
|
||||
Governance::submit_proposal(pobre, [7u8; 32], [8u8; 32], 100, MIN_PROPOSAL_STAKE),
|
||||
Governance::submit_proposal(
|
||||
pobre,
|
||||
[7u8; 32],
|
||||
[8u8; 32],
|
||||
VOTING_PERIOD,
|
||||
MIN_PROPOSAL_STAKE
|
||||
),
|
||||
Error::<Test>::StakeInsufficientBalance
|
||||
);
|
||||
});
|
||||
@@ -1133,7 +1153,7 @@ fn scenario_10_lifecycle_walkthrough_canonical() {
|
||||
assert_eq!(proposal.nay_weight, 1000);
|
||||
|
||||
// Step 3: advance + finalize canonical
|
||||
run_to_block(200);
|
||||
run_to_block(TRAS_EL_PERIODO);
|
||||
assert_ok!(Governance::finalize_proposal(alice_origin(), id));
|
||||
|
||||
// Verify final status canonical
|
||||
@@ -1252,7 +1272,7 @@ fn el_ogc_que_respalda_un_voto_no_sale_de_la_cuenta_mientras_el_voto_vive() {
|
||||
fn el_freeze_real_es_el_mayor_de_los_votos_vivos_no_el_ultimo() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let corta = submit_default(alice_origin());
|
||||
let larga = propuesta_con_periodo(11, 3 * VOTING_PERIOD);
|
||||
let larga = propuesta_con_periodo(11, 2 * VOTING_PERIOD);
|
||||
let saldo = Balances::free_balance(bob_account());
|
||||
assert_ok!(Governance::cast_vote(
|
||||
bob_origin(),
|
||||
@@ -1292,7 +1312,7 @@ fn el_freeze_real_es_el_mayor_de_los_votos_vivos_no_el_ultimo() {
|
||||
fn al_vencer_el_voto_grande_solo_queda_congelado_el_pequeno_que_sigue_vivo() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let corta = submit_default(alice_origin());
|
||||
let larga = propuesta_con_periodo(11, 3 * VOTING_PERIOD);
|
||||
let larga = propuesta_con_periodo(11, 2 * VOTING_PERIOD);
|
||||
assert_ok!(Governance::cast_vote(
|
||||
bob_origin(),
|
||||
larga,
|
||||
@@ -1462,7 +1482,7 @@ fn un_voto_vencido_no_revive_con_el_siguiente() {
|
||||
fn el_mismo_ogc_entero_vota_en_dos_propuestas() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let p1 = submit_default(alice_origin());
|
||||
let p2 = propuesta_con_periodo(11, 3 * VOTING_PERIOD);
|
||||
let p2 = propuesta_con_periodo(11, 2 * VOTING_PERIOD);
|
||||
let saldo = Balances::free_balance(bob_account());
|
||||
assert_ok!(Governance::cast_vote(
|
||||
bob_origin(),
|
||||
@@ -1615,7 +1635,7 @@ fn el_limite_es_de_votos_vivos_y_los_vencidos_no_ocupan_sitio() {
|
||||
let corta = submit_default(alice_origin());
|
||||
let mut largas = Vec::new();
|
||||
for semilla in 11..15u8 {
|
||||
largas.push(propuesta_con_periodo(semilla, 3 * VOTING_PERIOD));
|
||||
largas.push(propuesta_con_periodo(semilla, 2 * VOTING_PERIOD));
|
||||
}
|
||||
assert_ok!(Governance::cast_vote(
|
||||
bob_origin(),
|
||||
@@ -1646,3 +1666,529 @@ fn el_limite_es_de_votos_vivos_y_los_vencidos_no_ocupan_sitio() {
|
||||
assert_eq!(crate::VoteLocks::<Test>::get(bob_account()).len(), 4);
|
||||
});
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// RV16 — el override de un veto del council es un 4/5 REAL de la comunidad.
|
||||
// Doctrina: council veta con 2/3, la comunidad revierte con 4/5. Hallazgo C3
|
||||
// de SUPER_AUDIT_V1, demostrado otra vez por la revisión adversaria de RV15.
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
/// 1 OGC en unidades base (MIN_PROPOSAL_STAKE son 1.000 OGC). Los importes de los
|
||||
/// tests de RV16 van en OGC reales: el quórum del mock es 1.000 OGC, y con unidades
|
||||
/// base sueltas ningún override lo alcanzaría (me pasó al escribirlos).
|
||||
const OGC: u128 = MIN_PROPOSAL_STAKE / 1_000;
|
||||
|
||||
/// Council de 1 (Alice) y propuesta de Alice vetada en el acto (bloque 1).
|
||||
fn propuesta_vetada() -> (ProposalId, u64) {
|
||||
use crate::pallet::CouncilRole;
|
||||
use frame_support::dispatch::RawOrigin;
|
||||
assert_ok!(Governance::add_council_member(
|
||||
RawOrigin::Root.into(),
|
||||
alice_account(),
|
||||
CouncilRole::Chair,
|
||||
));
|
||||
let id = submit_default(alice_origin());
|
||||
assert_ok!(Governance::veto_proposal(alice_origin(), id));
|
||||
let cierre = crate::OverrideDeadline::<Test>::get(id).expect("el veto abre la ventana");
|
||||
(id, cierre)
|
||||
}
|
||||
|
||||
fn estado(id: ProposalId) -> ProposalStatus {
|
||||
Proposals::<Test>::get(id).expect("propuesta").status
|
||||
}
|
||||
|
||||
/// C3: el bond que el veto devuelve no basta para revertirlo. El quórum (aquí 2.000
|
||||
/// OGC; 100M en el runtime) está por encima del bond (1.000) a propósito, y lo exige
|
||||
/// `integrity_test`. La primera versión de este test usaba 800 OGC y pasaba porque
|
||||
/// 800 no llegaba a un quórum IGUAL al bond: con el bond entero, revertía (revisión
|
||||
/// de RV16). Ahora el bond entero no basta, y el doble sí, si nadie sostiene.
|
||||
#[test]
|
||||
fn el_bond_devuelto_no_basta_para_revertir_el_veto() {
|
||||
for (revertir, revierte) in [(MIN_PROPOSAL_STAKE, false), (2 * MIN_PROPOSAL_STAKE, true)] {
|
||||
new_test_ext().execute_with(|| {
|
||||
let (id, cierre) = propuesta_vetada();
|
||||
assert_ok!(Governance::override_council_veto(
|
||||
alice_origin(),
|
||||
id,
|
||||
revertir
|
||||
));
|
||||
run_to_block(cierre + 1);
|
||||
assert_ok!(Governance::finalize_override(bob_origin(), id));
|
||||
let aprobada = matches!(estado(id), ProposalStatus::Approved);
|
||||
assert_eq!(aprobada, revierte, "el proponente revierte con {revertir}");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// La regla es MONÓTONA: sostener el veto nunca ayuda a revertirlo. La primera
|
||||
/// versión de RV16 contaba sostener para el quórum y la revisión demostró que, con
|
||||
/// Aye 9.000 / Nay 1.000, Charlie revertía el veto votando SOSTENER con 1.000, y lo
|
||||
/// defendía no votando. Ahora: revertir 9.000 contra quórum 10.000 pasa sin nadie
|
||||
/// enfrente, y cada OGC que sostiene solo sube el listón (2.250 aún no, 2.251 sí).
|
||||
#[test]
|
||||
fn sostener_el_veto_nunca_ayuda_a_revertirlo() {
|
||||
let casos = [
|
||||
(0u128, true),
|
||||
(1_000, true),
|
||||
(2_000, true),
|
||||
(2_250, true),
|
||||
(2_251, false),
|
||||
];
|
||||
let mut anterior = true;
|
||||
for (sostener, esperado) in casos {
|
||||
let aprobada = new_test_ext().execute_with(|| {
|
||||
use crate::pallet::CouncilRole;
|
||||
use frame_support::dispatch::RawOrigin;
|
||||
assert_ok!(Governance::add_council_member(
|
||||
RawOrigin::Root.into(),
|
||||
alice_account(),
|
||||
CouncilRole::Chair,
|
||||
));
|
||||
let id = submit_default(alice_origin());
|
||||
assert_ok!(Governance::cast_vote(
|
||||
bob_origin(),
|
||||
id,
|
||||
VoteStance::Aye,
|
||||
9_000 * OGC
|
||||
));
|
||||
assert_ok!(Governance::cast_vote(
|
||||
charlie_origin(),
|
||||
id,
|
||||
VoteStance::Nay,
|
||||
1_000 * OGC
|
||||
));
|
||||
assert_ok!(Governance::veto_proposal(alice_origin(), id));
|
||||
let cierre = crate::OverrideDeadline::<Test>::get(id).expect("ventana");
|
||||
assert_ok!(Governance::override_council_veto(
|
||||
bob_origin(),
|
||||
id,
|
||||
9_000 * OGC
|
||||
));
|
||||
if sostener > 0 {
|
||||
assert_ok!(Governance::uphold_council_veto(
|
||||
charlie_origin(),
|
||||
id,
|
||||
sostener * OGC
|
||||
));
|
||||
}
|
||||
run_to_block(cierre + 1);
|
||||
assert_ok!(Governance::finalize_override(alice_origin(), id));
|
||||
matches!(estado(id), ProposalStatus::Approved)
|
||||
});
|
||||
assert_eq!(aprobada, esperado, "sostener {sostener} OGC");
|
||||
assert!(
|
||||
anterior || !aprobada,
|
||||
"sostener {sostener} OGC ayudó a revertir"
|
||||
);
|
||||
anterior = aprobada;
|
||||
}
|
||||
}
|
||||
|
||||
/// Quien quiere el veto puede DEFENDERLO, y el 4/5 se mide sobre la participación:
|
||||
/// 4/5 exacto revierte; un poco menos lo sostiene.
|
||||
#[test]
|
||||
fn quien_voto_nay_puede_sostener_el_veto_y_el_umbral_es_4_de_5_exacto() {
|
||||
for (sostener, revierte) in [(2_000 * OGC, true), (2_000 * OGC + 1, false)] {
|
||||
new_test_ext().execute_with(|| {
|
||||
let (id, cierre) = propuesta_vetada();
|
||||
// 8.000 OGC revertir (Bob) contra `sostener` (Charlie): 8.000/10.000 = 4/5 exacto.
|
||||
assert_ok!(Governance::override_council_veto(
|
||||
bob_origin(),
|
||||
id,
|
||||
8_000 * OGC
|
||||
));
|
||||
assert_ok!(Governance::uphold_council_veto(
|
||||
charlie_origin(),
|
||||
id,
|
||||
sostener
|
||||
));
|
||||
run_to_block(cierre + 1);
|
||||
assert_ok!(Governance::finalize_override(alice_origin(), id));
|
||||
let aprobada = matches!(estado(id), ProposalStatus::Approved);
|
||||
assert_eq!(
|
||||
aprobada, revierte,
|
||||
"revertir 8.000 contra sostener {sostener}"
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Un voto no voltea nada a mitad de ventana: el resultado se decide al cerrarla.
|
||||
/// Antes, cruzar el umbral aprobaba en el acto, antes de que nadie pudiera sostener.
|
||||
#[test]
|
||||
fn el_override_se_decide_al_cerrar_la_ventana_no_al_cruzar_un_umbral() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let (id, cierre) = propuesta_vetada();
|
||||
let saldo = Balances::free_balance(bob_account());
|
||||
assert_ok!(Governance::override_council_veto(bob_origin(), id, saldo));
|
||||
assert!(
|
||||
matches!(estado(id), ProposalStatus::Rejected),
|
||||
"100% y sigue vetada"
|
||||
);
|
||||
|
||||
run_to_block(cierre);
|
||||
assert_noop!(
|
||||
Governance::finalize_override(alice_origin(), id),
|
||||
Error::<Test>::OverrideWindowOpen
|
||||
);
|
||||
run_to_block(cierre + 1);
|
||||
assert_ok!(Governance::finalize_override(alice_origin(), id));
|
||||
assert!(matches!(estado(id), ProposalStatus::Approved));
|
||||
});
|
||||
}
|
||||
|
||||
/// El quórum, fijado en el veto, es el MAYOR entre MinOverrideQuorum y la
|
||||
/// participación del voto original contando Aye + Nay (la abstención NO cuenta: el
|
||||
/// mismo OGC abstenido en muchas propuestas inflaría el quórum de todas sin aparecer
|
||||
/// en ninguna ventana). Con Aye 1.000 + Nay 2.000 + Abstain 2.000, el quórum es
|
||||
/// 3.000, y revertir solo, sin nadie que sostenga, necesita 4/5 de él: 2.400.
|
||||
#[test]
|
||||
fn el_quorum_es_aye_mas_nay_del_voto_original_y_se_fija_en_el_veto() {
|
||||
for (revertir, revierte) in [(2_400 * OGC - 1, false), (2_400 * OGC, true)] {
|
||||
new_test_ext().execute_with(|| {
|
||||
use crate::pallet::CouncilRole;
|
||||
use frame_support::dispatch::RawOrigin;
|
||||
assert_ok!(Governance::add_council_member(
|
||||
RawOrigin::Root.into(),
|
||||
alice_account(),
|
||||
CouncilRole::Chair,
|
||||
));
|
||||
let id = submit_default(alice_origin());
|
||||
assert_ok!(Governance::cast_vote(
|
||||
alice_origin(),
|
||||
id,
|
||||
VoteStance::Aye,
|
||||
1_000 * OGC
|
||||
));
|
||||
assert_ok!(Governance::cast_vote(
|
||||
bob_origin(),
|
||||
id,
|
||||
VoteStance::Nay,
|
||||
2_000 * OGC
|
||||
));
|
||||
assert_ok!(Governance::cast_vote(
|
||||
charlie_origin(),
|
||||
id,
|
||||
VoteStance::Abstain,
|
||||
2_000 * OGC
|
||||
));
|
||||
assert_ok!(Governance::veto_proposal(alice_origin(), id));
|
||||
assert_eq!(crate::OverrideQuorum::<Test>::get(id), Some(3_000 * OGC));
|
||||
let cierre = crate::OverrideDeadline::<Test>::get(id).expect("ventana");
|
||||
assert_ok!(Governance::override_council_veto(
|
||||
bob_origin(),
|
||||
id,
|
||||
revertir
|
||||
));
|
||||
run_to_block(cierre + 1);
|
||||
assert_ok!(Governance::finalize_override(alice_origin(), id));
|
||||
let aprobada = matches!(estado(id), ProposalStatus::Approved);
|
||||
assert_eq!(
|
||||
aprobada, revierte,
|
||||
"revertir {revertir} con quórum 3.000 OGC"
|
||||
);
|
||||
if !revierte {
|
||||
System::assert_last_event(RuntimeEvent::Governance(Event::CouncilVetoUpheld {
|
||||
id,
|
||||
override_stake: revertir,
|
||||
uphold_stake: 0,
|
||||
quorum: 3_000 * OGC,
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// El quórum que decide es el GUARDADO en el veto, no uno recalculado al final: un
|
||||
/// upgrade que cambie el parámetro no mueve la meta de una ventana abierta.
|
||||
#[test]
|
||||
fn finalize_override_usa_el_quorum_fijado_en_el_veto() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let (id, cierre) = propuesta_vetada();
|
||||
assert_eq!(
|
||||
crate::OverrideQuorum::<Test>::get(id),
|
||||
Some(2 * MIN_PROPOSAL_STAKE)
|
||||
);
|
||||
assert_ok!(Governance::override_council_veto(
|
||||
bob_origin(),
|
||||
id,
|
||||
MIN_PROPOSAL_STAKE
|
||||
));
|
||||
// Simula un quórum guardado más bajo: si finalize recalculara, no lo vería.
|
||||
crate::OverrideQuorum::<Test>::insert(id, MIN_PROPOSAL_STAKE);
|
||||
run_to_block(cierre + 1);
|
||||
assert_ok!(Governance::finalize_override(alice_origin(), id));
|
||||
assert!(matches!(estado(id), ProposalStatus::Approved));
|
||||
assert!(crate::OverrideQuorum::<Test>::get(id).is_none());
|
||||
});
|
||||
}
|
||||
|
||||
/// Los votos del mismo lado se SUMAN, en los dos lados.
|
||||
#[test]
|
||||
fn los_votos_del_mismo_lado_se_suman() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let (id, cierre) = propuesta_vetada();
|
||||
assert_ok!(Governance::override_council_veto(
|
||||
bob_origin(),
|
||||
id,
|
||||
4_000 * OGC
|
||||
));
|
||||
assert_ok!(Governance::override_council_veto(
|
||||
alice_origin(),
|
||||
id,
|
||||
4_000 * OGC
|
||||
));
|
||||
assert_ok!(Governance::uphold_council_veto(
|
||||
charlie_origin(),
|
||||
id,
|
||||
2_000 * OGC
|
||||
));
|
||||
assert_eq!(crate::OverrideStakeTotal::<Test>::get(id), 8_000 * OGC);
|
||||
run_to_block(cierre + 1);
|
||||
assert_ok!(Governance::finalize_override(alice_origin(), id));
|
||||
assert!(
|
||||
matches!(estado(id), ProposalStatus::Approved),
|
||||
"8.000 de 10.000"
|
||||
);
|
||||
});
|
||||
new_test_ext().execute_with(|| {
|
||||
let (id, cierre) = propuesta_vetada();
|
||||
assert_ok!(Governance::override_council_veto(
|
||||
bob_origin(),
|
||||
id,
|
||||
8_000 * OGC
|
||||
));
|
||||
assert_ok!(Governance::uphold_council_veto(
|
||||
charlie_origin(),
|
||||
id,
|
||||
1_000 * OGC
|
||||
));
|
||||
assert_ok!(Governance::uphold_council_veto(
|
||||
alice_origin(),
|
||||
id,
|
||||
1_000 * OGC + 1
|
||||
));
|
||||
assert_eq!(crate::UpholdStakeTotal::<Test>::get(id), 2_000 * OGC + 1);
|
||||
run_to_block(cierre + 1);
|
||||
assert_ok!(Governance::finalize_override(alice_origin(), id));
|
||||
assert!(
|
||||
matches!(estado(id), ProposalStatus::Rejected),
|
||||
"8.000 de 10.000+1"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Quien vota revertir no vuelve a votar en la ventana, ni en el mismo lado ni en el
|
||||
/// otro: sin esto, el mismo OGC revertiría hasta MaxActiveVotes veces.
|
||||
#[test]
|
||||
fn quien_revierte_no_vuelve_a_votar_en_la_ventana() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let (id, _) = propuesta_vetada();
|
||||
let saldo = Balances::free_balance(bob_account());
|
||||
assert_ok!(Governance::override_council_veto(bob_origin(), id, saldo));
|
||||
System::assert_last_event(RuntimeEvent::Governance(Event::OverrideVoteCast {
|
||||
id,
|
||||
voter: bob_account(),
|
||||
uphold: false,
|
||||
weight: saldo,
|
||||
}));
|
||||
assert_noop!(
|
||||
Governance::override_council_veto(bob_origin(), id, saldo),
|
||||
Error::<Test>::AlreadyOverrideVoted
|
||||
);
|
||||
assert_noop!(
|
||||
Governance::uphold_council_veto(bob_origin(), id, 1),
|
||||
Error::<Test>::AlreadyOverrideVoted
|
||||
);
|
||||
assert_eq!(crate::OverrideStakeTotal::<Test>::get(id), saldo);
|
||||
assert_eq!(crate::VoteLocks::<Test>::get(bob_account()).len(), 1);
|
||||
});
|
||||
}
|
||||
|
||||
/// SOSTENER pasa por las mismas puertas que revertir: advisor, voto popular,
|
||||
/// propuesta aún en votación, sin ventana, ventana cerrada y peso 0.
|
||||
#[test]
|
||||
fn sostener_pasa_por_las_mismas_puertas_que_revertir() {
|
||||
new_test_ext().execute_with(|| {
|
||||
use frame_support::dispatch::RawOrigin;
|
||||
let (id, cierre) = propuesta_vetada();
|
||||
assert_noop!(
|
||||
Governance::uphold_council_veto(charlie_origin(), id, 0),
|
||||
Error::<Test>::ZeroWeightWindowVote
|
||||
);
|
||||
assert_noop!(
|
||||
Governance::override_council_veto(charlie_origin(), id, 0),
|
||||
Error::<Test>::ZeroWeightWindowVote
|
||||
);
|
||||
assert_ok!(Governance::mark_as_advisor(
|
||||
RawOrigin::Root.into(),
|
||||
charlie_account()
|
||||
));
|
||||
assert_noop!(
|
||||
Governance::uphold_council_veto(charlie_origin(), id, 1),
|
||||
Error::<Test>::AdvisorMayNotVote
|
||||
);
|
||||
// Propuesta todavía en votación.
|
||||
let viva = propuesta_con_periodo(12, VOTING_PERIOD);
|
||||
assert_noop!(
|
||||
Governance::uphold_council_veto(bob_origin(), viva, 1),
|
||||
Error::<Test>::ProposalNotRejected
|
||||
);
|
||||
// Rechazada por voto popular: no es un veto.
|
||||
run_to_block(fin_de(viva) + 1);
|
||||
assert_ok!(Governance::finalize_proposal(bob_origin(), viva));
|
||||
assert_noop!(
|
||||
Governance::uphold_council_veto(bob_origin(), viva, 1),
|
||||
Error::<Test>::ProposalNotVetoRejected
|
||||
);
|
||||
// Ventana cerrada.
|
||||
run_to_block(cierre + 1);
|
||||
assert_noop!(
|
||||
Governance::uphold_council_veto(bob_origin(), id, 1),
|
||||
Error::<Test>::OverrideWindowClosed
|
||||
);
|
||||
});
|
||||
new_test_ext().execute_with(|| {
|
||||
// Veto sin ventana registrada: falla cerrado también al sostener.
|
||||
let id = submit_default(alice_origin());
|
||||
let mut p = Proposals::<Test>::get(id).expect("propuesta");
|
||||
p.status = ProposalStatus::Rejected;
|
||||
Proposals::<Test>::insert(id, p);
|
||||
crate::VetoRejected::<Test>::insert(id, ());
|
||||
assert_noop!(
|
||||
Governance::uphold_council_veto(bob_origin(), id, 1),
|
||||
Error::<Test>::OverrideWindowClosed
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Una cuenta vota una vez en la ventana, en un solo lado; el peso de sostener
|
||||
/// también sale del saldo y queda congelado hasta el cierre.
|
||||
#[test]
|
||||
fn una_cuenta_vota_una_vez_en_la_ventana_y_sostener_tambien_congela() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let (id, cierre) = propuesta_vetada();
|
||||
let saldo = Balances::free_balance(charlie_account());
|
||||
assert_noop!(
|
||||
Governance::uphold_council_veto(charlie_origin(), id, saldo + 1),
|
||||
Error::<Test>::VoteWeightExceedsBalance
|
||||
);
|
||||
assert_ok!(Governance::uphold_council_veto(charlie_origin(), id, 500));
|
||||
assert_eq!(congelado_por_votos(&charlie_account()), 500);
|
||||
assert_eq!(
|
||||
crate::VoteLocks::<Test>::get(charlie_account())[0].until,
|
||||
cierre
|
||||
);
|
||||
System::assert_last_event(RuntimeEvent::Governance(Event::OverrideVoteCast {
|
||||
id,
|
||||
voter: charlie_account(),
|
||||
uphold: true,
|
||||
weight: 500,
|
||||
}));
|
||||
assert_noop!(
|
||||
Governance::override_council_veto(charlie_origin(), id, 1),
|
||||
Error::<Test>::AlreadyOverrideVoted
|
||||
);
|
||||
assert_noop!(
|
||||
Governance::uphold_council_veto(charlie_origin(), id, 1),
|
||||
Error::<Test>::AlreadyOverrideVoted
|
||||
);
|
||||
// Control positivo: otra cuenta sí vota.
|
||||
assert_ok!(Governance::override_council_veto(bob_origin(), id, 1));
|
||||
});
|
||||
}
|
||||
|
||||
/// El override se decide una sola vez, y solo sobre un veto.
|
||||
#[test]
|
||||
fn el_override_se_decide_una_sola_vez_y_solo_sobre_un_veto() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let (id, cierre) = propuesta_vetada();
|
||||
run_to_block(cierre + 1);
|
||||
assert_ok!(Governance::finalize_override(bob_origin(), id));
|
||||
// Decidido: no queda ventana ni quórum guardados (estado limpio, no basura).
|
||||
assert!(crate::OverrideDeadline::<Test>::get(id).is_none());
|
||||
assert!(crate::OverrideQuorum::<Test>::get(id).is_none());
|
||||
assert_noop!(
|
||||
Governance::finalize_override(bob_origin(), id),
|
||||
Error::<Test>::OverrideNotPending
|
||||
);
|
||||
// Una propuesta rechazada por VOTO POPULAR no tiene override que decidir.
|
||||
let otra = propuesta_con_periodo(12, VOTING_PERIOD);
|
||||
assert_ok!(Governance::cast_vote(
|
||||
charlie_origin(),
|
||||
otra,
|
||||
VoteStance::Nay,
|
||||
10
|
||||
));
|
||||
run_to_block(fin_de(otra) + 1);
|
||||
assert_ok!(Governance::finalize_proposal(bob_origin(), otra));
|
||||
assert_noop!(
|
||||
Governance::finalize_override(bob_origin(), otra),
|
||||
Error::<Test>::ProposalNotVetoRejected
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// El veto solo cabe DURANTE el periodo de voto: antes podía llegar entre el fin
|
||||
/// del periodo y el finalize, y ganaba quien llamara primero.
|
||||
#[test]
|
||||
fn el_veto_solo_cabe_durante_el_periodo_de_voto() {
|
||||
new_test_ext().execute_with(|| {
|
||||
use crate::pallet::CouncilRole;
|
||||
use frame_support::dispatch::RawOrigin;
|
||||
assert_ok!(Governance::add_council_member(
|
||||
RawOrigin::Root.into(),
|
||||
alice_account(),
|
||||
CouncilRole::Chair,
|
||||
));
|
||||
let tarde = submit_default(alice_origin());
|
||||
let a_tiempo = propuesta_con_periodo(12, VOTING_PERIOD);
|
||||
run_to_block(fin_de(tarde) + 1);
|
||||
assert_noop!(
|
||||
Governance::veto_proposal(alice_origin(), tarde),
|
||||
Error::<Test>::VotingPeriodClosed
|
||||
);
|
||||
// Control positivo: en el último bloque de su periodo, sí.
|
||||
run_to_block(fin_de(a_tiempo));
|
||||
assert_ok!(Governance::veto_proposal(alice_origin(), a_tiempo));
|
||||
assert!(matches!(estado(a_tiempo), ProposalStatus::Rejected));
|
||||
});
|
||||
}
|
||||
|
||||
/// Una propuesta ORDINARIA dura al menos 14 días (PILAR_4 §6.6). La primera versión
|
||||
/// de RV16 ponía 48 h, que es la vía de emergencia sin sus 5/7 endosos: cualquiera la
|
||||
/// obtenía y elegía cuánto tiempo tenía el council para vetar (revisión de RV16).
|
||||
#[test]
|
||||
fn una_propuesta_ordinaria_dura_al_menos_14_dias() {
|
||||
new_test_ext().execute_with(|| {
|
||||
use crate::pallet::{
|
||||
DEFAULT_VOTING_PERIOD_BLOCKS, EMERGENCY_VOTING_PERIOD_BLOCKS, MIN_VOTING_PERIOD_BLOCKS,
|
||||
};
|
||||
assert_eq!(MIN_VOTING_PERIOD_BLOCKS, DEFAULT_VOTING_PERIOD_BLOCKS);
|
||||
assert_eq!(MIN_VOTING_PERIOD_BLOCKS, 14 * 24 * 600);
|
||||
for corto in [
|
||||
0u64,
|
||||
EMERGENCY_VOTING_PERIOD_BLOCKS,
|
||||
MIN_VOTING_PERIOD_BLOCKS - 1,
|
||||
] {
|
||||
assert_noop!(
|
||||
Governance::submit_proposal(
|
||||
alice_origin(),
|
||||
TITLE_HASH,
|
||||
BODY_HASH,
|
||||
corto,
|
||||
MIN_PROPOSAL_STAKE,
|
||||
),
|
||||
Error::<Test>::VotingPeriodTooShort
|
||||
);
|
||||
}
|
||||
// Control positivo: el mínimo exacto se acepta.
|
||||
assert_ok!(Governance::submit_proposal(
|
||||
alice_origin(),
|
||||
TITLE_HASH,
|
||||
BODY_HASH,
|
||||
MIN_VOTING_PERIOD_BLOCKS,
|
||||
MIN_PROPOSAL_STAKE,
|
||||
));
|
||||
});
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
//! procedimiento completo y el hardware al que hay que creerle).
|
||||
//!
|
||||
//! GENERADO POR SUBSTRATE BENCHMARK CLI VERSION 51.0.0
|
||||
//! FECHA: 2026-09-24, STEPS: `50`, REPEAT: `20`
|
||||
//! FECHA: 2026-10-07, STEPS: `50`, REPEAT: `20`
|
||||
//! HOSTNAME: `MacBookProM3Max.local`, CPU: `<UNKNOWN>`
|
||||
//! WASM-EXECUTION: `Compiled`, DB CACHE: 1024
|
||||
|
||||
@@ -80,6 +80,10 @@ pub trait WeightInfo {
|
||||
fn endorse_emergency_proposal() -> Weight;
|
||||
/// Peso de `unlock_vote_funds` — MEDIDO sobre el WASM, no estimado a mano.
|
||||
fn unlock_vote_funds() -> Weight;
|
||||
/// Peso de `uphold_council_veto` — MEDIDO sobre el WASM, no estimado a mano.
|
||||
fn uphold_council_veto() -> Weight;
|
||||
/// Peso de `finalize_override` — MEDIDO sobre el WASM, no estimado a mano.
|
||||
fn finalize_override() -> Weight;
|
||||
}
|
||||
|
||||
/// Weights parametrizados por el `DbWeight` real del runtime.
|
||||
@@ -105,8 +109,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Proof size en bytes:
|
||||
// Medido: `107`
|
||||
// Estimado: `3722`
|
||||
// Tiempo minimo de ejecucion: 54_000_000 picosegundos.
|
||||
Weight::from_parts(55_000_000, 0)
|
||||
// Tiempo minimo de ejecucion: 44_000_000 picosegundos.
|
||||
Weight::from_parts(45_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3722))
|
||||
.saturating_add(T::DbWeight::get().reads(7_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(5_u64))
|
||||
@@ -135,8 +139,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Proof size en bytes:
|
||||
// Medido: `2320`
|
||||
// Estimado: `5338`
|
||||
// Tiempo minimo de ejecucion: 46_000_000 picosegundos.
|
||||
Weight::from_parts(48_000_000, 0)
|
||||
// Tiempo minimo de ejecucion: 38_000_000 picosegundos.
|
||||
Weight::from_parts(42_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 5338))
|
||||
.saturating_add(T::DbWeight::get().reads(10_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(6_u64))
|
||||
@@ -161,8 +165,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Proof size en bytes:
|
||||
// Medido: `614`
|
||||
// Estimado: `6196`
|
||||
// Tiempo minimo de ejecucion: 61_000_000 picosegundos.
|
||||
Weight::from_parts(62_000_000, 0)
|
||||
// Tiempo minimo de ejecucion: 52_000_000 picosegundos.
|
||||
Weight::from_parts(59_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6196))
|
||||
.saturating_add(T::DbWeight::get().reads(9_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(6_u64))
|
||||
@@ -183,8 +187,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Proof size en bytes:
|
||||
// Medido: `25`
|
||||
// Estimado: `3554`
|
||||
// Tiempo minimo de ejecucion: 12_000_000 picosegundos.
|
||||
Weight::from_parts(12_000_000, 0)
|
||||
// Tiempo minimo de ejecucion: 10_000_000 picosegundos.
|
||||
Weight::from_parts(10_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3554))
|
||||
.saturating_add(T::DbWeight::get().reads(6_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(4_u64))
|
||||
@@ -205,8 +209,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Proof size en bytes:
|
||||
// Medido: `153`
|
||||
// Estimado: `3554`
|
||||
// Tiempo minimo de ejecucion: 13_000_000 picosegundos.
|
||||
Weight::from_parts(14_000_000, 0)
|
||||
// Tiempo minimo de ejecucion: 11_000_000 picosegundos.
|
||||
Weight::from_parts(12_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3554))
|
||||
.saturating_add(T::DbWeight::get().reads(6_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(4_u64))
|
||||
@@ -215,12 +219,12 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
/// Proof: `Governance::Council` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::Proposals` (r:1 w:1)
|
||||
/// Proof: `Governance::Proposals` (`max_values`: None, `max_size`: Some(257), added: 2732, mode: `MaxEncodedLen`)
|
||||
/// Storage: `System::Number` (r:1 w:0)
|
||||
/// Proof: `System::Number` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::CouncilSize` (r:1 w:0)
|
||||
/// Proof: `Governance::CouncilSize` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::VetoVotes` (r:6 w:1)
|
||||
/// Proof: `Governance::VetoVotes` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `MaxEncodedLen`)
|
||||
/// Storage: `System::Number` (r:1 w:0)
|
||||
/// Proof: `System::Number` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::ProposalBond` (r:1 w:1)
|
||||
/// Proof: `Governance::ProposalBond` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Balances::TotalIssuance` (r:1 w:0)
|
||||
@@ -235,6 +239,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
/// Proof: `System::Events` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Governance::OverrideDeadline` (r:0 w:1)
|
||||
/// Proof: `Governance::OverrideDeadline` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::OverrideQuorum` (r:0 w:1)
|
||||
/// Proof: `Governance::OverrideQuorum` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::VetoRejected` (r:0 w:1)
|
||||
/// Proof: `Governance::VetoRejected` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::VetoCount` (r:0 w:1)
|
||||
@@ -243,11 +249,11 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Proof size en bytes:
|
||||
// Medido: `1440`
|
||||
// Estimado: `16416`
|
||||
// Tiempo minimo de ejecucion: 109_000_000 picosegundos.
|
||||
Weight::from_parts(112_000_000, 0)
|
||||
// Tiempo minimo de ejecucion: 91_000_000 picosegundos.
|
||||
Weight::from_parts(95_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 16416))
|
||||
.saturating_add(T::DbWeight::get().reads(21_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(10_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(11_u64))
|
||||
}
|
||||
/// Storage: `Governance::AdvisorFlags` (r:1 w:1)
|
||||
/// Proof: `Governance::AdvisorFlags` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`)
|
||||
@@ -263,8 +269,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Proof size en bytes:
|
||||
// Medido: `25`
|
||||
// Estimado: `3513`
|
||||
// Tiempo minimo de ejecucion: 9_000_000 picosegundos.
|
||||
Weight::from_parts(10_000_000, 0)
|
||||
// Tiempo minimo de ejecucion: 8_000_000 picosegundos.
|
||||
Weight::from_parts(9_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3513))
|
||||
.saturating_add(T::DbWeight::get().reads(5_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(3_u64))
|
||||
@@ -283,13 +289,13 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Proof size en bytes:
|
||||
// Medido: `98`
|
||||
// Estimado: `3513`
|
||||
// Tiempo minimo de ejecucion: 11_000_000 picosegundos.
|
||||
Weight::from_parts(11_000_000, 0)
|
||||
// Tiempo minimo de ejecucion: 10_000_000 picosegundos.
|
||||
Weight::from_parts(10_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3513))
|
||||
.saturating_add(T::DbWeight::get().reads(5_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(3_u64))
|
||||
}
|
||||
/// Storage: `Governance::Proposals` (r:1 w:1)
|
||||
/// Storage: `Governance::Proposals` (r:1 w:0)
|
||||
/// Proof: `Governance::Proposals` (`max_values`: None, `max_size`: Some(257), added: 2732, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::VetoRejected` (r:1 w:0)
|
||||
/// Proof: `Governance::VetoRejected` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`)
|
||||
@@ -297,6 +303,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
/// Proof: `Governance::AdvisorFlags` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::OverrideVotes` (r:1 w:1)
|
||||
/// Proof: `Governance::OverrideVotes` (`max_values`: None, `max_size`: Some(112), added: 2587, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::UpholdVotes` (r:1 w:0)
|
||||
/// Proof: `Governance::UpholdVotes` (`max_values`: None, `max_size`: Some(112), added: 2587, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::OverrideDeadline` (r:1 w:0)
|
||||
/// Proof: `Governance::OverrideDeadline` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`)
|
||||
/// Storage: `System::Number` (r:1 w:0)
|
||||
@@ -319,11 +327,11 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Proof size en bytes:
|
||||
// Medido: `2468`
|
||||
// Estimado: `5338`
|
||||
// Tiempo minimo de ejecucion: 56_000_000 picosegundos.
|
||||
Weight::from_parts(58_000_000, 0)
|
||||
// Tiempo minimo de ejecucion: 47_000_000 picosegundos.
|
||||
Weight::from_parts(49_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 5338))
|
||||
.saturating_add(T::DbWeight::get().reads(13_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(7_u64))
|
||||
.saturating_add(T::DbWeight::get().reads(14_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(6_u64))
|
||||
}
|
||||
/// Storage: `Governance::Council` (r:1 w:0)
|
||||
/// Proof: `Governance::Council` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`)
|
||||
@@ -351,8 +359,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Proof size en bytes:
|
||||
// Medido: `353`
|
||||
// Estimado: `6132`
|
||||
// Tiempo minimo de ejecucion: 68_000_000 picosegundos.
|
||||
Weight::from_parts(69_000_000, 0)
|
||||
// Tiempo minimo de ejecucion: 58_000_000 picosegundos.
|
||||
Weight::from_parts(60_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6132))
|
||||
.saturating_add(T::DbWeight::get().reads(11_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(6_u64))
|
||||
@@ -377,8 +385,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Proof size en bytes:
|
||||
// Medido: `494`
|
||||
// Estimado: `6196`
|
||||
// Tiempo minimo de ejecucion: 56_000_000 picosegundos.
|
||||
Weight::from_parts(58_000_000, 0)
|
||||
// Tiempo minimo de ejecucion: 48_000_000 picosegundos.
|
||||
Weight::from_parts(49_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6196))
|
||||
.saturating_add(T::DbWeight::get().reads(9_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(5_u64))
|
||||
@@ -399,8 +407,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Proof size en bytes:
|
||||
// Medido: `101`
|
||||
// Estimado: `3593`
|
||||
// Tiempo minimo de ejecucion: 43_000_000 picosegundos.
|
||||
Weight::from_parts(43_000_000, 0)
|
||||
// Tiempo minimo de ejecucion: 37_000_000 picosegundos.
|
||||
Weight::from_parts(38_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3593))
|
||||
.saturating_add(T::DbWeight::get().reads(6_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(3_u64))
|
||||
@@ -423,8 +431,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Proof size en bytes:
|
||||
// Medido: `153`
|
||||
// Estimado: `6132`
|
||||
// Tiempo minimo de ejecucion: 22_000_000 picosegundos.
|
||||
Weight::from_parts(23_000_000, 0)
|
||||
// Tiempo minimo de ejecucion: 19_000_000 picosegundos.
|
||||
Weight::from_parts(20_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6132))
|
||||
.saturating_add(T::DbWeight::get().reads(8_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(3_u64))
|
||||
@@ -449,100 +457,180 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Proof size en bytes:
|
||||
// Medido: `2197`
|
||||
// Estimado: `5338`
|
||||
// Tiempo minimo de ejecucion: 34_000_000 picosegundos.
|
||||
Weight::from_parts(40_000_000, 0)
|
||||
// Tiempo minimo de ejecucion: 29_000_000 picosegundos.
|
||||
Weight::from_parts(30_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 5338))
|
||||
.saturating_add(T::DbWeight::get().reads(8_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(5_u64))
|
||||
}
|
||||
/// Storage: `Governance::Proposals` (r:1 w:0)
|
||||
/// Proof: `Governance::Proposals` (`max_values`: None, `max_size`: Some(257), added: 2732, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::VetoRejected` (r:1 w:0)
|
||||
/// Proof: `Governance::VetoRejected` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::AdvisorFlags` (r:1 w:0)
|
||||
/// Proof: `Governance::AdvisorFlags` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::OverrideVotes` (r:1 w:0)
|
||||
/// Proof: `Governance::OverrideVotes` (`max_values`: None, `max_size`: Some(112), added: 2587, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::UpholdVotes` (r:1 w:1)
|
||||
/// Proof: `Governance::UpholdVotes` (`max_values`: None, `max_size`: Some(112), added: 2587, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::OverrideDeadline` (r:1 w:0)
|
||||
/// Proof: `Governance::OverrideDeadline` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`)
|
||||
/// Storage: `System::Number` (r:1 w:0)
|
||||
/// Proof: `System::Number` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::VoteLocks` (r:1 w:1)
|
||||
/// Proof: `Governance::VoteLocks` (`max_values`: None, `max_size`: Some(1873), added: 4348, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Balances::Freezes` (r:1 w:1)
|
||||
/// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Balances::Locks` (r:1 w:0)
|
||||
/// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`)
|
||||
/// Storage: `System::ExecutionPhase` (r:1 w:0)
|
||||
/// Proof: `System::ExecutionPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `MaxEncodedLen`)
|
||||
/// Storage: `System::EventCount` (r:1 w:1)
|
||||
/// Proof: `System::EventCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `System::Events` (r:1 w:1)
|
||||
/// Proof: `System::Events` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
/// Storage: `Governance::UpholdStakeTotal` (r:1 w:1)
|
||||
/// Proof: `Governance::UpholdStakeTotal` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`)
|
||||
fn uphold_council_veto() -> Weight {
|
||||
// Proof size en bytes:
|
||||
// Medido: `2468`
|
||||
// Estimado: `5338`
|
||||
// Tiempo minimo de ejecucion: 47_000_000 picosegundos.
|
||||
Weight::from_parts(50_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 5338))
|
||||
.saturating_add(T::DbWeight::get().reads(14_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(6_u64))
|
||||
}
|
||||
/// Storage: `Governance::Proposals` (r:1 w:1)
|
||||
/// Proof: `Governance::Proposals` (`max_values`: None, `max_size`: Some(257), added: 2732, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::VetoRejected` (r:1 w:0)
|
||||
/// Proof: `Governance::VetoRejected` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::OverrideDeadline` (r:1 w:1)
|
||||
/// Proof: `Governance::OverrideDeadline` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`)
|
||||
/// Storage: `System::Number` (r:1 w:0)
|
||||
/// Proof: `System::Number` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::OverrideStakeTotal` (r:1 w:0)
|
||||
/// Proof: `Governance::OverrideStakeTotal` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::UpholdStakeTotal` (r:1 w:0)
|
||||
/// Proof: `Governance::UpholdStakeTotal` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`)
|
||||
/// Storage: `Governance::OverrideQuorum` (r:1 w:1)
|
||||
/// Proof: `Governance::OverrideQuorum` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`)
|
||||
/// Storage: `System::ExecutionPhase` (r:1 w:0)
|
||||
/// Proof: `System::ExecutionPhase` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `MaxEncodedLen`)
|
||||
/// Storage: `System::EventCount` (r:1 w:1)
|
||||
/// Proof: `System::EventCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
|
||||
/// Storage: `System::Events` (r:1 w:1)
|
||||
/// Proof: `System::Events` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
|
||||
fn finalize_override() -> Weight {
|
||||
// Proof size en bytes:
|
||||
// Medido: `636`
|
||||
// Estimado: `3722`
|
||||
// Tiempo minimo de ejecucion: 25_000_000 picosegundos.
|
||||
Weight::from_parts(26_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3722))
|
||||
.saturating_add(T::DbWeight::get().reads(10_u64))
|
||||
.saturating_add(T::DbWeight::get().writes(5_u64))
|
||||
}
|
||||
}
|
||||
|
||||
/// Impl para mocks y tests — `RocksDbWeight` directo, sin necesitar `T`.
|
||||
impl WeightInfo for () {
|
||||
fn submit_proposal() -> Weight {
|
||||
Weight::from_parts(55_000_000, 0)
|
||||
Weight::from_parts(45_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3722))
|
||||
.saturating_add(RocksDbWeight::get().reads(7_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(5_u64))
|
||||
}
|
||||
fn cast_vote() -> Weight {
|
||||
Weight::from_parts(48_000_000, 0)
|
||||
Weight::from_parts(42_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 5338))
|
||||
.saturating_add(RocksDbWeight::get().reads(10_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(6_u64))
|
||||
}
|
||||
fn finalize_proposal() -> Weight {
|
||||
Weight::from_parts(62_000_000, 0)
|
||||
Weight::from_parts(59_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6196))
|
||||
.saturating_add(RocksDbWeight::get().reads(9_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(6_u64))
|
||||
}
|
||||
fn add_council_member() -> Weight {
|
||||
Weight::from_parts(12_000_000, 0)
|
||||
Weight::from_parts(10_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3554))
|
||||
.saturating_add(RocksDbWeight::get().reads(6_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(4_u64))
|
||||
}
|
||||
fn remove_council_member() -> Weight {
|
||||
Weight::from_parts(14_000_000, 0)
|
||||
Weight::from_parts(12_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3554))
|
||||
.saturating_add(RocksDbWeight::get().reads(6_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(4_u64))
|
||||
}
|
||||
fn veto_proposal() -> Weight {
|
||||
Weight::from_parts(112_000_000, 0)
|
||||
Weight::from_parts(95_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 16416))
|
||||
.saturating_add(RocksDbWeight::get().reads(21_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(10_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(11_u64))
|
||||
}
|
||||
fn mark_as_advisor() -> Weight {
|
||||
Weight::from_parts(10_000_000, 0)
|
||||
Weight::from_parts(9_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3513))
|
||||
.saturating_add(RocksDbWeight::get().reads(5_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(3_u64))
|
||||
}
|
||||
fn unmark_as_advisor() -> Weight {
|
||||
Weight::from_parts(11_000_000, 0)
|
||||
Weight::from_parts(10_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3513))
|
||||
.saturating_add(RocksDbWeight::get().reads(5_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(3_u64))
|
||||
}
|
||||
fn override_council_veto() -> Weight {
|
||||
Weight::from_parts(58_000_000, 0)
|
||||
Weight::from_parts(49_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 5338))
|
||||
.saturating_add(RocksDbWeight::get().reads(13_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(7_u64))
|
||||
.saturating_add(RocksDbWeight::get().reads(14_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(6_u64))
|
||||
}
|
||||
fn submit_emergency_proposal() -> Weight {
|
||||
Weight::from_parts(69_000_000, 0)
|
||||
Weight::from_parts(60_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6132))
|
||||
.saturating_add(RocksDbWeight::get().reads(11_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(6_u64))
|
||||
}
|
||||
fn treasury_disbursement() -> Weight {
|
||||
Weight::from_parts(58_000_000, 0)
|
||||
Weight::from_parts(49_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6196))
|
||||
.saturating_add(RocksDbWeight::get().reads(9_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(5_u64))
|
||||
}
|
||||
fn treasury_deposit() -> Weight {
|
||||
Weight::from_parts(43_000_000, 0)
|
||||
Weight::from_parts(38_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3593))
|
||||
.saturating_add(RocksDbWeight::get().reads(6_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(3_u64))
|
||||
}
|
||||
fn endorse_emergency_proposal() -> Weight {
|
||||
Weight::from_parts(23_000_000, 0)
|
||||
Weight::from_parts(20_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6132))
|
||||
.saturating_add(RocksDbWeight::get().reads(8_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(3_u64))
|
||||
}
|
||||
fn unlock_vote_funds() -> Weight {
|
||||
Weight::from_parts(40_000_000, 0)
|
||||
Weight::from_parts(30_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 5338))
|
||||
.saturating_add(RocksDbWeight::get().reads(8_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(5_u64))
|
||||
}
|
||||
fn uphold_council_veto() -> Weight {
|
||||
Weight::from_parts(50_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 5338))
|
||||
.saturating_add(RocksDbWeight::get().reads(14_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(6_u64))
|
||||
}
|
||||
fn finalize_override() -> Weight {
|
||||
Weight::from_parts(26_000_000, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3722))
|
||||
.saturating_add(RocksDbWeight::get().reads(10_u64))
|
||||
.saturating_add(RocksDbWeight::get().writes(5_u64))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -584,6 +672,8 @@ mod guard {
|
||||
("treasury_deposit", <() as WeightInfo>::treasury_deposit()),
|
||||
("endorse_emergency_proposal", <() as WeightInfo>::endorse_emergency_proposal()),
|
||||
("unlock_vote_funds", <() as WeightInfo>::unlock_vote_funds()),
|
||||
("uphold_council_veto", <() as WeightInfo>::uphold_council_veto()),
|
||||
("finalize_override", <() as WeightInfo>::finalize_override()),
|
||||
];
|
||||
for (nombre, w) in casos {
|
||||
assert!(
|
||||
|
||||
Reference in new issue
Block a user