fix(runtime+emission): audit ultra 2026-07-02 — 3 fixes verificados en fuente (RV 5→6)

Audit ultra-profundo (Fable 5, refute-by-default): 3 dimensiones completadas
(economía, fee-path, attestation) → 23 hallazgos crudos → verificación manual
en fuente de los HIGH. Los 3 inequívocos, corregidos:

(a) FeeMultiplierUpdate = () COLAPSABA NextFeeMultiplier a 0 tras el bloque 1
    [HIGH]: impl<A, B: Default> Convert<A,B> for () devuelve Default (=0) y
    on_finalize hace *fm = convert(*fm) — el componente weight-fee desaparecía
    de TODA la cadena desde el bloque 2. Verificado en pallet-transaction-
    payment-43.0.0 src (líneas 158-171, 446-448). Fix: ConstFeeMultiplier<1>
    + test de regresión fee_multiplier_update_never_collapses_to_zero.

(b) NativeToEthRatio = 1_000_000 con comentario "OGC 12 decimals" [HIGH]:
    OGC tiene 18 decimales (Ogc::DECIMALS=18) = precisión ETH ⇒ ratio 1:1.
    El 10^6 (herencia del template de 12 dec) distorsionaba TODO valor visto
    por la capa EVM ×10^6. Fix: ConstU32<1> + test derivado de la delta de
    decimales (guard de coherencia, no número mágico).

(c) Emisión: let _ = mint_into ×3 descartaba resultados [MEDIUM] mientras
    TotalEmitted y el evento BlockRewardMinted registraban incondicionalmente
    ⇒ la contabilidad podía mentir si un mint fallaba (e.g. bajo ED). Fix:
    TotalEmitted + evento registran SOLO lo realmente acuñado.

RUNTIME_VERSION 5→6 (cambios de comportamiento; TRANSACTION_VERSION intacto).
Workspace verde: 272 checks, 0 fallos. Pendientes de decisión de David (Level
A economía): emisión-mint vs Ecosystem 400M pool (doble fuente del mismo
propósito) · IdentityFee dust con 18 decimales (calibración WeightToFee).
Audit continúa post-reset (6 dimensiones + verify formal de los 23).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
davidherranandClaude Fable 5 committed 2026-07-03 10:22:05 -05:00
1 parent 1a0364db99
commit 7b8863fd47
3 files changed
+82 -23

No files matched your search

+41 -10
View File
@@ -236,7 +236,14 @@ pub const IMPL_NAME: &str = "origin-chain-charon";
/// v5: FeesApi alignment — nuevo método `query_fee_for_account` (estima el fee
/// con el TierProfile REAL on-chain del account, no caller-supplied). Cambia la
/// metadata del Runtime API FeesApi; método aditivo ⇒ TRANSACTION_VERSION intacto.
pub const RUNTIME_VERSION: u32 = 5;
/// v6: audit ultra 2026-07-02 (3 fixes) — (a) `FeeMultiplierUpdate`: `()` colapsaba
/// `NextFeeMultiplier` a 0 tras el bloque 1 (weight-fee desaparecía de la cadena);
/// ahora `ConstFeeMultiplier<1>`. (b) `NativeToEthRatio` 1_000_000→1 (OGC = 18
/// decimales, no 12; la capa EVM distorsionaba valores ×10^6). (c) emisión:
/// `TotalEmitted` + evento registran SOLO lo realmente acuñado (resultados de
/// `mint_into` ya no se descartan). Cambia comportamiento ⇒ spec bump;
/// TRANSACTION_VERSION intacto.
pub const RUNTIME_VERSION: u32 = 6;
/// Canonical authoring version per Substrate semver canonical.
pub const AUTHORING_VERSION: u32 = 1;
@@ -828,11 +835,12 @@ mod tests {
use super::*;
#[test]
fn runtime_version_v5_fees_api_account_alignment() {
// v5 = FeesApi.query_fee_for_account (estima con el TierProfile real
// on-chain). Método aditivo al Runtime API ⇒ los calls/extrinsics
// EXISTENTES no cambian su formato ⇒ TRANSACTION_VERSION intacto.
assert_eq!(RUNTIME_VERSION, 5);
fn runtime_version_v6_ultra_audit_fixes() {
// v6 = 3 fixes del audit ultra 2026-07-02: ConstFeeMultiplier (el `()`
// colapsaba NextFeeMultiplier a 0), NativeToEthRatio=1 (OGC 18 dec),
// y emisión con contabilidad honesta de mint_into. Cambios de
// comportamiento, no de formato de extrinsic ⇒ TRANSACTION_VERSION intacto.
assert_eq!(RUNTIME_VERSION, 6);
assert_eq!(TRANSACTION_VERSION, 1);
}
@@ -913,12 +921,35 @@ mod tests {
}
#[test]
fn revive_native_to_eth_ratio_one_million_canonical() {
// OGC 12 decimals → ETH 18 decimals = ratio 10^6 canonical.
// Mapping balance OGC↔ETH-equivalent units para EVM compat.
fn revive_native_to_eth_ratio_one_to_one() {
// OGC tiene 18 decimales (Ogc::DECIMALS) = la precisión de ETH ⇒ ratio
// 1:1. El 10^6 anterior era herencia del template (nativo 12 dec) y
// distorsionaba la capa EVM ×10^6 (audit ultra 2026-07-02, fix v6).
// Guard de coherencia: el ratio DEBE derivar de la delta de decimales.
use frame_support::traits::Get;
let ratio: u32 = <<Runtime as pallet_revive::Config>::NativeToEthRatio>::get();
assert_eq!(ratio, 1_000_000_u32);
const ETH_DECIMALS: u32 = 18;
let expected = 10_u32.pow(ETH_DECIMALS - origin_chain_types::Ogc::DECIMALS);
assert_eq!(ratio, expected);
assert_eq!(ratio, 1_u32);
}
#[test]
fn fee_multiplier_update_never_collapses_to_zero() {
// Regresión del audit ultra 2026-07-02: `FeeMultiplierUpdate = ()`
// devolvía Default (= 0) en cada on_finalize ⇒ NextFeeMultiplier
// colapsaba a 0 tras el bloque 1 y el weight-fee desaparecía de toda
// la cadena. El update JAMÁS puede mapear 1 → 0.
use pallet_transaction_payment::Multiplier;
use sp_runtime::traits::{Convert, Zero};
let one = Multiplier::from_u32(1);
let next =
<<Runtime as pallet_transaction_payment::Config>::FeeMultiplierUpdate as Convert<
Multiplier,
Multiplier,
>>::convert(one);
assert_eq!(next, one, "el multiplier debe permanecer en 1, no colapsar");
assert!(!next.is_zero());
}
#[test]