feat(fees,genesis): FeesApi account-aligned query + 250M Foundation→vault og/gvtry

Dos endurecimientos pre-mainnet (leftovers del remediation roadmap):

1. genesis vault (#16/CHN-4): el preset mainnet asigna el 25% Foundation Treasury
   (250M OGC) al VAULT de governance (og/gvtry, GovernanceTreasuryPalletId), NO a
   una cuenta key-controlada. Es la MISMA cuenta de la que treasury_disbursement
   gasta (gated por governance council) y que emission/staking alimentan → el
   treasury queda DAO-governed desde el bloque 0, materializando "Foundation
   Treasury → DAO governed (CHN-4)". El placeholder FNDT queda SOLO como sudo_key
   interim hasta el sunset (DC ORIGIN_CHAIN_GOVERNANCE_SUNSET_V1). Las allocations
   BM V2 (40/25/15/15/5 = 1B) no cambian de monto.

2. FeesApi alignment: nuevo método query_fee_for_account(action, base, account) que
   estima el fee con el TierProfile REAL on-chain del account (storage TierProfiles,
   ValueQuery default Desktop+Free), NO caller-supplied — alineado con el fee-path
   vivo OriginFeeAdapter (FIX-6 Stage 2a). Cierra el "el cliente adivinaba hw/sub":
   la estimación off-chain ahora usa la misma fórmula sobre el MISMO tier que cobra
   la cadena. Método aditivo al Runtime API ⇒ TRANSACTION_VERSION 1 intacto.

RUNTIME_VERSION 4→5 (nueva metadata de FeesApi). 268 workspace tests verde
(native, SKIP_WASM_BUILD — WASM VPS-gated), 0 regresión. Test sella que
query_fee_for_account usa el perfil real (EmbeddedArm piso < default Desktop).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
davidherranandClaude Opus 4.8 committed 2026-06-21 21:01:38 -05:00
1 parent 112747ab44
commit 8e72496901
4 files changed
+96 -12

No files matched your search

@@ -39,7 +39,7 @@
#![cfg(feature = "std")]
use crate::{
configs::{AuraId, GrandpaId},
configs::{AuraId, GovernanceTreasuryPalletId, GrandpaId},
opaque::SessionKeys,
Balance, ChainAccountId, Ogc, RuntimeGenesisConfig,
};
@@ -47,6 +47,7 @@ use alloc::vec;
use alloc::vec::Vec;
use origin_chain_types::{HardwareTier, SubscriptionTier};
use sp_genesis_builder::PresetId;
use sp_runtime::traits::AccountIdConversion;
// ============================================================
// Canonical constants para mainnet allocation (BM V2)
@@ -343,11 +344,19 @@ pub fn mainnet_genesis_config_genesis() -> RuntimeGenesisConfig {
};
let ecosystem_pool = make_placeholder(b"ECO!"); // Ecosystem/Rewards Pool canonical
let foundation_treasury = make_placeholder(b"FNDT"); // Foundation Treasury canonical
let foundation_treasury = make_placeholder(b"FNDT"); // Foundation multisig = sudo_key interim
let public_sale = make_placeholder(b"SALE"); // Public Sale canonical
let founding_team = make_placeholder(b"TEAM"); // Founding Team canonical (4yr vesting)
let exchange_liquidity = make_placeholder(b"LIQD"); // Exchange Liquidity canonical
// El 25% Foundation Treasury (250M) se asigna al VAULT de governance (og/gvtry),
// NO a una cuenta key-controlada — materializa "DAO governed (CHN-4)" desde el
// bloque 0. Es la MISMA cuenta de la que `treasury_disbursement` gasta (gated por
// governance council) y que emission/staking alimentan. El placeholder FNDT queda
// SOLO como sudo_key interim (Root) hasta el sunset a governance pre-mainnet.
let governance_vault: ChainAccountId =
GovernanceTreasuryPalletId::get().into_account_truncating();
// 5 initial validators canonical Pi 5 placeholders (Dream House Studios + universities).
let validators = vec![
placeholder_mainnet_validator(0),
@@ -361,15 +370,16 @@ pub fn mainnet_genesis_config_genesis() -> RuntimeGenesisConfig {
// BM V2 allocation canonical exact: 40/25/15/15/5 → 1B OGC total
vec![
(ecosystem_pool, ECOSYSTEM_ALLOCATION),
(foundation_treasury.clone(), FOUNDATION_ALLOCATION),
(governance_vault, FOUNDATION_ALLOCATION), // 250M → vault og/gvtry (DAO-governed)
(public_sale, PUBLIC_SALE_ALLOCATION),
(founding_team, FOUNDING_TEAM_ALLOCATION),
(exchange_liquidity, EXCHANGE_LIQUIDITY_ALLOCATION),
],
validators,
// FIX-5: Foundation Treasury = sudo key interim (Root) en mainnet
// (multisig humano). PRE-LAUNCH Q1 2027: David ratifica la key real +
// sunset a governance (pallet-collective/referenda).
// FIX-5: el placeholder FNDT (Foundation multisig humano) = sudo key interim
// (Root) en mainnet. PRE-LAUNCH Q1 2027: David ratifica la key real + sunset
// a governance (pallet-collective/referenda). El treasury (250M) ya NO vive
// aquí — está en el vault og/gvtry, gastable solo vía governance.
foundation_treasury,
// FIX-6 Stage 2a: mainnet arranca SIN perfiles sembrados — todos en el
// Default conservador (Desktop+Free) hasta que la attestation real
+20 -6
View File
@@ -233,7 +233,10 @@ pub const IMPL_NAME: &str = "origin-chain-charon";
/// en pallet-origin-emission Index 13: nuevo call ⇒ cambia metadata. El call es
/// aditivo en un call_index nuevo — TRANSACTION_VERSION intacto). Palanca Root
/// para pausar inflación + kill-switch anti-doble-emisión para la activación NPoS.
pub const RUNTIME_VERSION: u32 = 4;
/// 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;
/// Canonical authoring version per Substrate semver canonical.
pub const AUTHORING_VERSION: u32 = 1;
@@ -660,6 +663,17 @@ impl_runtime_apis! {
) -> u64 {
Fees::query_fee(action, base, hw, sub)
}
fn query_fee_for_account(
action: origin_chain_types::ChainAction,
base: u64,
account: origin_chain_types::AccountId,
) -> u64 {
// account es el newtype origin_chain_types::AccountId; el storage key
// canonical es ChainAccountId = AccountId32 (32-byte, bytes-level).
let runtime_account = ChainAccountId::from(account.0);
Fees::query_fee_for_account(action, base, &runtime_account)
}
}
// ============================================================
@@ -814,11 +828,11 @@ mod tests {
use super::*;
#[test]
fn runtime_version_v4_emission_kill_switch() {
// v4 = FIX-6 Stage 2b governance emission kill-switch (nuevo call en
// Emission Index 13). El formato de extrinsic de los calls EXISTENTES NO
// cambió (call aditivo en call_index nuevo) ⇒ TRANSACTION_VERSION intacto.
assert_eq!(RUNTIME_VERSION, 4);
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);
assert_eq!(TRANSACTION_VERSION, 1);
}