test(governance): el hueco del peso de voto ya tiene donde vivir — test en rojo con control positivo (RV15)
Palace lo midio el 2026-09-06 y escribio que no era explotable porque el nodo
no arrancaba. Desde 63918f3 el nodo arranca. Confirmado hoy: cast_vote y
override_council_veto suman el stake_weight que DECLARA el votante sin
contrastarlo con nada. El diseño dice «1 OGC = 1 voto» (lib.rs:403); el codigo
suma lo que le digan.
Impacto medido, no supuesto: hoy NO drena la tesoreria, porque
treasury_disbursement exige ademas ensure_root. Si permite aprobar o bloquear
cualquier propuesta con u128::MAX y revertir un veto del council. El dia que se
retire el sudo (L-7) y la gobernanza ejecute (L-8), si la drena.
El test va con ignore y no lo esconde: con --ignored sale en rojo hoy («un voto
de peso 10^22+1 con saldo 10^22 fue ACEPTADO»). Lleva control positivo: el
saldo entero si vota y cuenta entero, para que una «cura» que rechace TODO voto
no pueda cerrarlo. Quitar el ignore es el criterio de cierre de RV15: peso
derivado del saldo + un freeze para que el mismo OGC no vote dos veces pasando
por una transferencia.
cargo test -p origin-chain-governance: 51 passed, 1 ignored.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
63918f365b
commit
d37a278ba6
1 file changed
+40
@@ -1144,3 +1144,43 @@ fn scenario_10_lifecycle_walkthrough_canonical() {
|
|||||||
assert!(matches!(vote_bob, VoteStance::Aye));
|
assert!(matches!(vote_bob, VoteStance::Aye));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// HUECO ABIERTO — medido por Palace el 2026-09-06, confirmado por Charon el
|
||||||
|
/// 2026-09-23 sobre `63918f3`. `cast_vote` (y `override_council_veto`) suman el
|
||||||
|
/// `stake_weight` que DECLARA el votante sin contrastarlo con nada: el diseño dice
|
||||||
|
/// «1 OGC = 1 voto» (doc de `lib.rs:403`) y el código es un contador que suma lo que
|
||||||
|
/// le digan. Hoy no drena la tesorería porque `treasury_disbursement` exige además
|
||||||
|
/// `ensure_root`, pero cualquiera aprueba o bloquea una propuesta con `u128::MAX`,
|
||||||
|
/// y el día que se retire el sudo (L-7) y la gobernanza ejecute (L-8) sí la drena.
|
||||||
|
///
|
||||||
|
/// El `ignore` NO lo esconde: `cargo test -- --ignored` lo enseña en rojo, y
|
||||||
|
/// QUITARLO es el criterio de cierre de RV15 (peso derivado del saldo + un freeze
|
||||||
|
/// para que el mismo OGC no vote dos veces pasando por una transferencia).
|
||||||
|
#[test]
|
||||||
|
#[ignore = "RV15: cast_vote acepta el peso que declara el votante (hueco medido 2026-09-06)"]
|
||||||
|
fn un_voto_no_puede_pesar_mas_que_el_saldo_del_votante() {
|
||||||
|
new_test_ext().execute_with(|| {
|
||||||
|
let id = submit_default(alice_origin());
|
||||||
|
let saldo = Balances::free_balance(bob_account());
|
||||||
|
let r = Governance::cast_vote(bob_origin(), id, VoteStance::Aye, saldo + 1);
|
||||||
|
assert!(
|
||||||
|
r.is_err(),
|
||||||
|
"un voto de peso {} con saldo {} fue ACEPTADO",
|
||||||
|
saldo + 1,
|
||||||
|
saldo
|
||||||
|
);
|
||||||
|
let p = Proposals::<Test>::get(id).expect("propuesta existe");
|
||||||
|
assert_eq!(p.yes_weight, 0, "el peso inventado entró al recuento");
|
||||||
|
|
||||||
|
// Control positivo: sin él, una «cura» que rechazara TODO voto pasaría este
|
||||||
|
// test. El saldo entero sí vota, y cuenta entero.
|
||||||
|
assert_ok!(Governance::cast_vote(
|
||||||
|
bob_origin(),
|
||||||
|
id,
|
||||||
|
VoteStance::Aye,
|
||||||
|
saldo
|
||||||
|
));
|
||||||
|
let p = Proposals::<Test>::get(id).expect("propuesta existe");
|
||||||
|
assert_eq!(p.yes_weight, saldo, "un voto legítimo no contó entero");
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in new issue
Block a user