From d37a278ba6831f1aaf96f8e4acc8ddf6185089e7 Mon Sep 17 00:00:00 2001 From: Charon Date: Wed, 23 Sep 2026 20:17:55 -0500 Subject: [PATCH] =?UTF-8?q?test(governance):=20el=20hueco=20del=20peso=20d?= =?UTF-8?q?e=20voto=20ya=20tiene=20donde=20vivir=20=E2=80=94=20test=20en?= =?UTF-8?q?=20rojo=20con=20control=20positivo=20(RV15)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../src/tests_integration.rs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/crates/origin-chain-governance/src/tests_integration.rs b/crates/origin-chain-governance/src/tests_integration.rs index 6156140..4e21609 100644 --- a/crates/origin-chain-governance/src/tests_integration.rs +++ b/crates/origin-chain-governance/src/tests_integration.rs @@ -1144,3 +1144,43 @@ fn scenario_10_lifecycle_walkthrough_canonical() { 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::::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::::get(id).expect("propuesta existe"); + assert_eq!(p.yes_weight, saldo, "un voto legítimo no contó entero"); + }); +}