Files
arkhe-origin-chain/crates/origin-chain-runtime/src/configs.rs
T
davidherranandClaude Fable 5 3364994cce feat(fees): FIX-6 Stage 2a — fee unificado (cierra V2-CA3)
Pone la fórmula OCAFB-5 en el fee-path VIVO: OriginFeeAdapter
(OnChargeTransaction custom) reemplaza al FungibleAdapter tier-blind.
El firmante paga su fracción según (HardwareTier × ChainAction ×
SubscriptionTier, tiers leídos ON-CHAIN de TierProfiles — jamás
caller-supplied), y el subsidy pool og/subsy (alimentado por la
emisión Stage 1) cubre la fracción subsidiada. Inmutable #16 en cada
transacción. OU=() = burn 100% gas fees (matriz CHN-2).

unified_fee (u128, outcome tipado FeeOutcome — sin el sentinel
u64::MAX in-band): user = fórmula vendor Mathi byte-fiel (test de
paridad grid contra ce4fafb); pool = net × subsidy_bp/1e4 sobre el
COSTO BASE (anti-regresivo, sub_mult ORTOGONAL: un Ultra NO drena el
pool más que un Free — el premium lo paga el usuario, no el commons).

Hallazgos de la verificación adversarial (workflow ultracode, 4
lentes) cerrados de raíz:
- HIGH: clasificador cubre eth_instantiate_with_code (call_index 10)
  — evadía el entitlement-gate DeployContract vía fallback Write.
- MEDIUM ledger envenenable: removido el dispatchable legacy
  compute_fee_for_action (tiers caller-supplied, escribía AccountFees
  sin cobrar). AccountFees ahora escrito SOLO por el fee-path vivo
  (note_settlement). Eventos que nunca se emitían eliminados; el
  preview read-only vive en query_fee / FeesApi.
- MEDIUM drenaje del pool por sub_mult: pool sobre net, no sobre el
  precio premium (Opción B anti-regresiva).
- Dev UX: GenesisConfig siembra perfiles iniciales; dev/local
  arrancan Ultra (los Slices 3.x de contracts no se bloquean por
  Free+DeployContract); mainnet vacío (Default conservador hasta
  attestation).

Decisión de diseño (autoridad Pilar 4): replay de attestation =
RECHAZO explícito, no dedup silencioso (notificado a Ergon para el
reference impl). Orden OCAFB-5 subsidy-antes-de-entitlement preservado
byte-fiel + notificado a Mathi para el ratify 2026-06-21.

set_tier_profile Root-only interim (sunset a attestation-driven vía
Mathi PerceptionAdapter + DID binding FIX-3/FIX-4). spec_version 1→2
(formato de extrinsic intacto, TRANSACTION_VERSION=1).

Tests: 49 crate fees (paridad grid + lobo blanco ortogonalidad +
refund + pool seco + tip passthrough + entitlement blocked) + 21
suites workspace verde. Toolchain cargo +1.88.

Nota WASM: el build local del runtime WASM falla en la
post-validación del substrate-wasm-builder con UnknownOpcode(252)
— límite del toolchain (Rust 1.88 emite opcodes 0xFC que el parser
del builder de stable2509 no deserializa). Reproducido idéntico en
el HEAD intacto (v0.0.57): es ambiental, no de este cambio. El node
real + WASM artifact siguen VPS-gated (toolchain alineado /
wasm32v1-none cuando el wasm-builder lo soporte).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 20:22:14 -05:00

635 lines
33 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! # Configs canonical de pallets para Origin Chain runtime
//!
//! Implementa los `Config` traits de cada pallet integrado, parametrizados con
//! valores canonical de Origin Chain per DCs `ORIGIN_CHAIN_FOUNDATION_V1`
//! (CHN-1..CHN-8) + `ORIGIN_CHAIN_SUBSTRATE_FOUNDATION_V1` (SBS-1..SBS-6) +
//! Business Model V2 (David ratificado 2026-05-18).
//!
//! ## Filosofía canonical incorporada
//!
//! Cada parámetro canonical materializa empíricamente alguna directiva del
//! ecosistema Origin:
//!
//! - **EXISTENTIAL_DEPOSIT canonical**: `1 MILLI_OGC` (0.001 OGC = 10^15 base
//! units). Permite que un usuario Pi 5 en escuela rural mantenga balance
//! activo con monto trivial (Inmutable #16 anti-clasista + Inmutable #37 FREE
//! perpetua). David canon 2026-05-14: *"la libertad infinita acota solo donde
//! empieza la del otro"* — el existential deposit es la frontera mínima
//! canonical sin la cual el chain no puede protegerse de spam infinito, pero
//! se mantiene tan baja que no excluye a nadie.
//!
//! - **BLOCK_HASH_COUNT canonical**: 2400 bloques × 6 segundos = 4 horas exactas
//! = ventana canonical de epoch rotation per CHN-1. Las pruebas de inclusión
//! por hash pueden refrenciar cualquier bloque del epoch en curso sin necesidad
//! de archival queries — eficiencia canonical para validators Pi 5.
//!
//! - **SS58_PREFIX canonical**: `42` (substrate dev default) para testnet.
//! Post-mainnet Q1 2027 se solicitará registro canonical en
//! `polkadot/ss58-registry` para asignar prefix permanente (e.g. `1888` para
//! Origin Chain — pendiente DC).
//!
//! - **MILLISECS_PER_BLOCK canonical**: 6000 ms = 6 segundos canonical per Aura
//! slot duration. Standard Substrate canonical, alineado con Polkadot block
//! time, suficiente para Pi 5 validators (CPU mínimo per CHN-1).
extern crate alloc;
use crate::{
Balance, BlockNumber, ChainAccountId, Ogc, PalletInfo, Runtime, RuntimeCall, RuntimeEvent,
RuntimeFreezeReason, RuntimeHoldReason, RuntimeOrigin, RuntimeTask,
};
use frame_support::derive_impl;
use frame_support::parameter_types;
use frame_support::traits::{ConstBool, ConstU32, ConstU64, VariantCountOf};
use frame_system::EnsureSigned;
use sp_runtime::Perbill;
// ============================================================
// Canonical constants (per CHN-1/2/8 + SBS-3)
// ============================================================
/// 1 OGC en base units canonical (10^18).
pub const OGC: Balance = Ogc::ONE;
/// 1 MILLI_OGC = 0.001 OGC = 10^15 base units canonical.
pub const MILLI_OGC: Balance = OGC / 1_000;
/// Existential deposit canonical: 1 MILLI_OGC.
///
/// Filosofía anti-clasista: el ED minimum debe ser trivial para cualquier user
/// (Pi 5 rural Africa = Vision Pro San Francisco). 0.001 OGC ≈ centavos a precios
/// post-mainnet razonables. Sin sacrificar protección anti-spam canonical.
pub const EXISTENTIAL_DEPOSIT: Balance = MILLI_OGC;
/// Block hash count canonical: 2400 bloques = 4 horas exactas (Aura 6s slot).
///
/// Alineado canonical con epoch rotation CHN-1 (4h selección de 100-150 active
/// validators canonical). Block hashes available para inclusion proofs durante
/// todo el epoch en curso sin archival queries.
pub const BLOCK_HASH_COUNT: BlockNumber = 2400;
/// SS58 prefix canonical para testnet. Post-mainnet: solicitar registro canonical
/// permanente en polkadot/ss58-registry (TBD DC complementaria).
pub const SS58_PREFIX: u16 = 42;
/// Milisegundos por bloque canonical: 6000 ms = 6s Aura slot.
pub const MILLISECS_PER_BLOCK: u64 = 6_000;
/// Slot duration canonical = block time canonical.
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
// ============================================================
// frame_system::Config canonical (using SolochainDefaultConfig prelude)
// ============================================================
parameter_types! {
/// SS58 prefix canonical wrapped per Substrate canonical pattern.
pub const SS58Prefix: u16 = SS58_PREFIX;
/// Block hash count canonical wrapped.
pub const BlockHashCount: BlockNumber = BLOCK_HASH_COUNT;
}
#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig)]
impl frame_system::Config for Runtime {
type Block = crate::Block;
type AccountId = ChainAccountId;
type Nonce = crate::Nonce;
type Hash = crate::Hash;
type BlockHashCount = BlockHashCount;
type AccountData = pallet_balances::AccountData<Balance>;
type SS58Prefix = SS58Prefix;
type MaxConsumers = ConstU32<16>;
}
// ============================================================
// pallet_balances::Config canonical (CHN-2 OGC + Inmutable #16/#37)
// ============================================================
parameter_types! {
/// Existential deposit canonical wrapped.
pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT;
/// Max locks canonical: 50 (Substrate standard, suficiente para staking +
/// democracy + governance simultáneos sin bloat).
pub const MaxLocks: u32 = 50;
}
impl pallet_balances::Config for Runtime {
type Balance = Balance;
type RuntimeEvent = RuntimeEvent;
type DustRemoval = ();
type ExistentialDeposit = ExistentialDeposit;
type AccountStore = frame_system::Pallet<Runtime>;
type MaxLocks = MaxLocks;
type MaxReserves = ();
type ReserveIdentifier = [u8; 8];
type FreezeIdentifier = RuntimeFreezeReason;
type MaxFreezes = VariantCountOf<RuntimeFreezeReason>;
type RuntimeHoldReason = RuntimeHoldReason;
type RuntimeFreezeReason = RuntimeFreezeReason;
type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
type DoneSlashHandler = ();
}
// ============================================================
// pallet_timestamp::Config canonical (foundational para Aura)
// ============================================================
parameter_types! {
/// Minimum period canonical entre bloques: SLOT_DURATION / 2 = 3 segundos.
/// Substrate canonical pattern para Aura compatibility.
pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
}
impl pallet_timestamp::Config for Runtime {
type Moment = u64;
/// `Aura` wired canonical post Phase 1.4: cada nuevo timestamp triggera el
/// Aura slot advance canonical. Materializa el coupling consensus↔clock que
/// hace posible 6-segundo block production deterministic canonical.
type OnTimestampSet = crate::Aura;
type MinimumPeriod = MinimumPeriod;
type WeightInfo = pallet_timestamp::weights::SubstrateWeight<Runtime>;
}
// ============================================================
// pallet_transaction_payment::Config canonical (CHN-8 fee economy)
// ============================================================
parameter_types! {
/// Operational fee multiplier canonical: 5x baseline canonical Substrate.
pub const OperationalFeeMultiplier: u8 = 5;
}
/// FIX-6 Stage 2a: clasificador call→ChainAction del fee unificado (taxonomía
/// OCAFB-2). Vive aquí porque el runtime es el único sitio donde `RuntimeCall`
/// es concreto. Fallback conservador: `Write` (fee estándar — un wildcard
/// jamás regala subsidio; mismo principio que la alerta TLB de Ergon).
pub struct OriginCallClassifier;
impl origin_chain_fees::ClassifyChainAction<crate::RuntimeCall> for OriginCallClassifier {
fn classify(call: &crate::RuntimeCall) -> origin_chain_fees::ChainAction {
use origin_chain_fees::ChainAction;
match call {
crate::RuntimeCall::Balances(
pallet_balances::Call::transfer_allow_death { .. }
| pallet_balances::Call::transfer_keep_alive { .. }
| pallet_balances::Call::transfer_all { .. },
) => ChainAction::Transfer,
crate::RuntimeCall::Revive(
pallet_revive::Call::instantiate { .. }
| pallet_revive::Call::instantiate_with_code { .. }
// call_index 10: el deploy vía la capa EVM (Code::Upload). Sin
// este arm caería en el fallback Write y evadiría el
// entitlement-gate DeployContract (HIGH del audit Stage 2a).
| pallet_revive::Call::eth_instantiate_with_code { .. },
) => ChainAction::DeployContract,
crate::RuntimeCall::Revive(
pallet_revive::Call::call { .. }
| pallet_revive::Call::eth_call { .. }
// eth_transact: envoltorio EVM genérico (puede ser call/deploy/
// transfer). Lo tratamos como ejecución de contrato — su
// entitlement (Free=false) y subsidio coinciden con CallContract;
// refinar cuando la capa EVM se cablee plenamente.
| pallet_revive::Call::eth_transact { .. },
) => ChainAction::CallContract,
crate::RuntimeCall::Revive(pallet_revive::Call::upload_code { .. }) => {
ChainAction::UploadContractCode
}
_ => ChainAction::Write,
}
}
}
impl pallet_transaction_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
/// FIX-6 Stage 2a (cierra V2-CA3): `OriginFeeAdapter` reemplaza al
/// `FungibleAdapter` default — la fórmula OCAFB-5 entra al fee-path VIVO:
/// el firmante paga su fracción según (HardwareTier × ChainAction ×
/// SubscriptionTier, tiers leídos ON-CHAIN de `TierProfiles`, jamás
/// caller-supplied), y el subsidy pool `og/subsy` (alimentado por la
/// emisión Index 13) cubre la fracción subsidiada — Inmutable #16 en cada
/// transacción. `OU = ()` deliberado: burn matrix CHN-2 ratificada = gas
/// fees 100% burn (el burn total = fee constitucional completo, deflación
/// que contrapesa la emisión Stage 1).
type OnChargeTransaction =
origin_chain_fees::OriginFeeAdapter<crate::Balances, (), OriginCallClassifier>;
type OperationalFeeMultiplier = OperationalFeeMultiplier;
type WeightToFee = frame_support::weights::IdentityFee<Balance>;
type LengthToFee = frame_support::weights::IdentityFee<Balance>;
type FeeMultiplierUpdate = ();
type WeightInfo = pallet_transaction_payment::weights::SubstrateWeight<Runtime>;
}
// ============================================================
// pallet_aura::Config canonical (CHN-1 — block production PoA)
// ============================================================
/// Canonical Aura authority id type. `sr25519` canonical per Substrate
/// standard — más eficiente que Ed25519 para slot signing canonical (Schnorr
/// signature aggregation futuro). Wallet identity sigue Ed25519 (CHN-7), pero
/// validator authority keys sr25519 per Substrate convention canonical.
pub type AuraId = sp_consensus_aura::sr25519::AuthorityId;
impl pallet_aura::Config for Runtime {
type AuthorityId = AuraId;
/// `DisabledValidators = ()`: Phase 1 PoA simple — no disable mechanism
/// canonical. Phase 2 NPoS introduces pallet_session disabling vía slashing.
type DisabledValidators = ();
/// `MaxAuthorities = 32`: canonical para Phase 1 PoA (5-7 validators
/// inaugurales + room para growth pre-NPoS). Aligned con polkadot-stable2512
/// solochain-template default canonical.
type MaxAuthorities = ConstU32<32>;
/// `AllowMultipleBlocksPerSlot = false`: canonical Substrate — un block por
/// slot. Disallow multiplicity para deterministic block time canonical Pi 5.
type AllowMultipleBlocksPerSlot = ConstBool<false>;
/// Slot duration canonical = `pallet_aura::MinimumPeriodTimesTwo<Runtime>` —
/// derivado automáticamente del `pallet_timestamp::MinimumPeriod` config
/// canonical. Garantiza coupling canonical entre clock + consensus slot.
type SlotDuration = pallet_aura::MinimumPeriodTimesTwo<Runtime>;
}
// ============================================================
// pallet_grandpa::Config canonical (CHN-1 — finality gadget)
// ============================================================
/// Canonical GRANDPA authority id type. `Ed25519` canonical per GRANDPA spec —
/// signature aggregation matemáticamente diferente a Aura sr25519 pero
/// canonical convention.
pub type GrandpaId = sp_consensus_grandpa::AuthorityId;
impl pallet_grandpa::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
/// `WeightInfo = ()`: Phase 1 PoA simple. Phase 2 NPoS introduces real
/// weights para equivocation reporting + on_finalize hooks canonical.
type WeightInfo = ();
/// `MaxAuthorities = 32`: aligned con Aura canonical para 1:1 mapping
/// validator ↔ finalizer Phase 1 PoA (mismo set canonical).
type MaxAuthorities = ConstU32<32>;
/// `MaxNominators = 0`: Phase 1 PoA simple — no nominators canonical (no
/// stake delegation aún). Phase 2 NPoS bump canonical a 256 nominators.
type MaxNominators = ConstU32<0>;
/// `MaxSetIdSessionEntries = 0`: Phase 1 simple — no historical session
/// proofs canonical. Phase 2 NPoS introduces session tracking.
type MaxSetIdSessionEntries = ConstU64<0>;
/// `KeyOwnerProof = sp_core::Void`: Phase 1 simple — no equivocation proof
/// type. Phase 2 NPoS introduces real `MembershipProof` canonical.
type KeyOwnerProof = sp_core::Void;
/// `EquivocationReportSystem = ()`: Phase 1 PoA simple — equivocation
/// reports not handled. Phase 2 NPoS introduces real handler canonical.
type EquivocationReportSystem = ();
}
// ============================================================
// pallet_session::Config canonical (CHN-1 — 4h epoch rotation)
// ============================================================
//
// Filosofía canonical: PoA Phase 1 preserva el mismo validator set canonical
// genesis através de cada session rotation (SessionManager = `()`). El "epoch
// rotation" canonical materializa el ritmo institucional canonical (cada 4h se
// emite SessionEvent canonical observable on-chain) sin cambiar canonical el
// validator set hasta Phase 2 NPoS — cuando pallet_staking introduce dynamic
// validator selection basado en stake + nominator delegation.
//
// CHN-1 ratificado canonical: "Epoch rotation every 4 hours selecting 100-150
// active validators from millions of Pi 5 nodes eligible". Phase 1 PoA tiene
// 5-7 static validators canonical; el "selecting 100-150" materializa Phase 2
// NPoS canonical. Esta integration Phase 1.5 establece el substrate canonical
// para que Phase 2 NPoS herede el rotation mechanism sin breakage.
parameter_types! {
/// Canonical session period: 2400 bloques × 6s = 14400s = **4 horas exactas**
/// per CHN-1 ratified canonical. Alineado canonical con BLOCK_HASH_COUNT
/// (mismo valor) — block hash proof valid durante todo el epoch en curso.
pub const SessionPeriod: BlockNumber = BLOCK_HASH_COUNT;
/// Canonical session offset: 0 — sesiones canonical start at block 0 (sin
/// offset canonical). Phase 2 NPoS puede introducir offset si necesario
/// para alinear con extramo institucional (e.g. UTC midnight epoch starts).
pub const SessionOffset: BlockNumber = 0;
}
/// Canonical converter `ChainAccountId → Option<ChainAccountId>`.
///
/// Phase 1 PoA simple: cada AccountId IS a ValidatorId canonical (identidad
/// trivial). Phase 2 NPoS introduces real Stash/Controller separation canonical
/// where ValidatorId derives from Stash account via pallet_staking::StashOf.
pub struct AccountIdIsValidatorId;
impl sp_runtime::traits::Convert<ChainAccountId, Option<ChainAccountId>>
for AccountIdIsValidatorId
{
fn convert(account: ChainAccountId) -> Option<ChainAccountId> {
Some(account)
}
}
impl pallet_session::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
/// ValidatorId canonical = ChainAccountId (Phase 1 PoA identidad trivial).
type ValidatorId = ChainAccountId;
/// ValidatorIdOf canonical: identity mapping AccountId → ValidatorId.
type ValidatorIdOf = AccountIdIsValidatorId;
/// ShouldEndSession canonical: PeriodicSessions every 2400 blocks (4h epoch
/// per CHN-1 canonical). Cada 2400 bloques emite SessionEvent::NewSession.
type ShouldEndSession = pallet_session::PeriodicSessions<SessionPeriod, SessionOffset>;
/// NextSessionRotation canonical: same PeriodicSessions — predecible
/// canonical para validators saber cuándo será el next rotation slot.
type NextSessionRotation = pallet_session::PeriodicSessions<SessionPeriod, SessionOffset>;
/// SessionManager canonical = `()`: Phase 1 PoA preserves genesis validators
/// canonical across all sessions (no rotation of validator SET, only
/// SessionId increment canonical). Phase 2 NPoS introduces pallet_staking
/// como SessionManager canonical para real rotation per nominator stake.
type SessionManager = ();
/// SessionHandler canonical: deriva desde opaque::SessionKeys (aura sr25519
/// + grandpa Ed25519). Cuando una nueva session begins canonical, los
/// session keys de cada validator se distribute al consensus pallets canonical
/// (Aura recibe nuevo AuraId set + Grandpa recibe nuevo GrandpaId set).
type SessionHandler =
<crate::opaque::SessionKeys as sp_runtime::traits::OpaqueKeys>::KeyTypeIdProviders;
/// Keys canonical = opaque::SessionKeys struct (defined en opaque.rs).
type Keys = crate::opaque::SessionKeys;
/// DisablingStrategy canonical = `()`: Phase 1 PoA simple — no validator
/// disable mechanism. Phase 2 NPoS introduces `UpToLimitWithReEnablingDisablingStrategy`
/// canonical para slashing-based validator disabling per CHN-3.
type DisablingStrategy = ();
/// **Stable2509-3 API additions (Ship 1.5 v0.0.38)**: pallet_session 43.0.0
/// requires Currency + KeyDeposit para session key registration deposit
/// economy. Phase 1 PoA simple: zero deposit canonical (genesis validators
/// static, no nominator-registered keys). Phase 2 NPoS introduces real
/// deposit canonical via parameter_type post-staking pallet integration.
type Currency = crate::Balances;
type KeyDeposit = frame_support::traits::ConstU128<0>;
type WeightInfo = pallet_session::weights::SubstrateWeight<Runtime>;
}
// ============================================================
// pallet_identity::Config — DEFERRED a Phase 2.7 (canonical decision empírica)
// ============================================================
//
// Decision canonical 2026-05-21: `pallet-identity 41.0.0` (stable2512 canonical)
// usa `ReservableCurrency` trait que está deprecated en stable2512 canonical
// (replaced canonical por `fungible::Mutate`). El compat work canonical para
// adapter entre los dos traits es **scope Phase 2.7** cuando se introduce el
// custom `pallet_agent_identity` canonical (per Inmutable #41 Cross-Species
// Co-authorship — AGI DIDs first-class citizens).
//
// **Wallet creation canonical FREE perpetua per Inmutable #37 ya está materializado
// vía `pallet_balances` canonical** — un account canonical existe simplemente con
// 1 MILLI_OGC EXISTENTIAL_DEPOSIT canonical. Identity metadata canonical
// (display name + email + GitHub + avatar + etc.) es feature *adicional canonical*
// que viene Phase 2.7.
//
// Pre-Phase 2.7: wallets canonical son AccountId32 (Ed25519/sr25519/ecdsa via
// MultiSignature canonical). Suficiente canonical para Phase 1 PoA + Phase 2
// NPoS basic. Identity claims canonical son value-add Phase 2.7+.
// ============================================================
// origin_chain_provenance::Config — Phase 2.1 v0.0.15 wired
// ============================================================
//
// pallet-origin-provenance scaffold canonical (DC PROVENANCE_PALLET_V1 5/10
// firmas, ratify target 2026-05-29). Scaffold-level Config canonical: solo
// RuntimeEvent association. Future canonical fields post DC ratify + Ergon
// arkhe-noesis-attestation-types Cap 42+ ship:
//
// - `OitFeeSchedule: Arc<dyn arkhe_amis_server::OitFeeSchedule>` (post OCAFB)
// - Custom origin canonical para validator-restricted attestation
// - Pallet weights canonical desde benchmarking real
impl origin_chain_provenance::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
}
// ============================================================
// origin_chain_fees::Config — Phase 2.4 v0.0.21 wired
// ============================================================
//
// pallet-origin-fees scaffold canonical (DC `origin_chain_amis_fee_bridge_v1`
// OCAFB-1..6 sesión 3+ 6/7 firmas, ratify target 2026-06-21). Scaffold-level
// Config canonical v0.0.21: solo RuntimeEvent association. Future canonical
// fields post-OCAFB ratify + Mathi sub-crate ship:
//
// - `OitFeeSchedule: Arc<dyn arkhe_amis_server::OitFeeSchedule>` (post-OCAFB
// ratify swap canonical cross-workspace)
// - Pallet weights canonical desde benchmarking real (post-Phase 4 testnet)
// - Custom origin canonical para fee waiver scenarios (governance Phase 5)
impl origin_chain_fees::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
/// FIX-6 Stage 2a: la MISMA constante que alimenta la emisión (Index 13)
/// — pool-alimentación y pool-consumo apuntan a la misma cuenta og/subsy
/// (jamás re-declarar el literal: un typo divergiría las cuentas).
type SubsidyPalletId = EmissionSubsidyPalletId;
}
// ============================================================
// origin_chain_agent_identity::Config — Phase 2.7 v0.0.25 wired
// ============================================================
//
// pallet-agent-identity scaffold canonical (Phase 2.7 AGI DIDs Inmutable #41
// AGI Cross-Species Co-authorship). Scaffold-level Config canonical v0.0.25:
// solo RuntimeEvent association. Future canonical fields post-Phase 2.7 DC
// ratify pending:
//
// - `MaxAgentChainLen: Get<u32>` (BoundedVec bound canonical para agent_chain)
// - Custom origin canonical para Hybrid agent registration (governance Phase 5)
// - Pallet weights canonical desde benchmarking real (post-Phase 4 testnet)
impl origin_chain_agent_identity::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
}
// ============================================================
// origin_chain_governance::Config — Phase 5.1 v0.0.29 wired
// ============================================================
//
// pallet-origin-governance scaffold canonical (Phase 5.1 Foundation Treasury
// Governance CHN-4 AI-Driven Human-Guarded). Scaffold-level Config canonical
// v0.0.29: solo RuntimeEvent association. Future canonical fields post-Phase 5
// DC ratify:
//
// - `MinProposalStake: Get<u128>` (1,000 OGC mínimum canonical CHN-4 5.3)
// - `MaxVotingPeriodBlocks: Get<u64>` (14-day period canonical 5.4)
// - Custom origin canonical para Technical Council veto (5.5)
// - `IsGovernanceAdvisor: Trait` (5.6 — humans-only vote enforcement)
parameter_types! {
/// FIX-6: PalletId de la cuenta-tesorería de governance (vault, sin private
/// key, determinística). Tiene el balance real OGC; solo la governance (Root)
/// la drena vía treasury_disbursement. PRE-LAUNCH: el genesis mainnet debe
/// rutear la Foundation 250M a esta cuenta (hoy va a FNDT — follow-up).
pub const GovernanceTreasuryPalletId: frame_support::PalletId =
frame_support::PalletId(*b"og/gvtry");
}
impl origin_chain_governance::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Currency = crate::Balances;
type TreasuryPalletId = GovernanceTreasuryPalletId;
}
// ============================================================
// origin_chain_emission::Config — FIX-6 Stage 1 (audit V2-CA2)
// ============================================================
//
// En cada bloque mintea EmissionBlockReward y lo reparte: 70% al autor (el
// validador Aura), 20% al treasury (og/gvtry, la MISMA cuenta de governance),
// 10% al subsidy pool (og/subsy, proof-of-equity que financia el subsidio de
// hardware #16 — ortogonal a la suscripción, David 2026-06-10). Cierra "los
// validadores ganan 0 OGC". FindAuthor = el mapeo Aura→validador de session.
//
// BlockReward 10 OGC × ~5.256M bloques/año ≈ 52.6M OGC/año ≈ 5.26% inflación
// sobre el genesis de 1B (materializa la emisión del 40% Ecosystem BM V2).
// Stage 2 introduce pallet_staking NPoS sobre este substrate.
parameter_types! {
/// Recompensa por bloque: 10 OGC (~5% inflación anual).
pub const EmissionBlockReward: Balance = 10 * OGC;
/// 70% al autor (validador Aura).
pub const EmissionAuthorShareBps: u16 = 7_000;
/// 20% al treasury (el residual 10% va al subsidy pool).
pub const EmissionTreasuryShareBps: u16 = 2_000;
/// PalletId del subsidy pool (proof-of-equity, #16 anti-clasista).
pub const EmissionSubsidyPalletId: frame_support::PalletId =
frame_support::PalletId(*b"og/subsy");
}
impl origin_chain_emission::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Currency = crate::Balances;
/// Aura → validador account vía pallet_session (FindAccountFromAuthorIndex).
type FindAuthor = pallet_session::FindAccountFromAuthorIndex<Runtime, crate::Aura>;
type BlockReward = EmissionBlockReward;
type AuthorShareBps = EmissionAuthorShareBps;
type TreasuryShareBps = EmissionTreasuryShareBps;
// Reusa el MISMO vault de governance (og/gvtry) para el treasury.
type TreasuryPalletId = GovernanceTreasuryPalletId;
type SubsidyPalletId = EmissionSubsidyPalletId;
}
// ============================================================
// pallet_revive::Config — Phase 3 Slice 3.1 v0.0.39 wired
// ============================================================
//
// Smart contracts PolkaVM RISC-V WASM execution per SBS-5 ratificado
// (supersedes CHN-6 v1.0 → ink! v6 + Solidity vía revive compiler). Wired
// runtime Index 11 con associated types per Asset Hub Westend stable2509-3
// reference adaptado. pallet-revive 0.10.1 via git source polkadot-stable2509-3
// tag (post workspace bump Ship 1.5 v0.0.38 atómico).
//
// **Decisiones canonical Slice 3.1 SCAFFOLD interim** (refinement Phase 3.x maduración):
//
// - `Precompiles = ()`: empty tuple — sin custom precompiles canonical Slice 3.1.
// Phase 3.x añade ERC20 precompile (cross-asset compat) + custom Origin
// precompiles (provenance hooks + fees integration).
// - `FindAuthor = ()`: returns None canonical — sin pallet_authorship integration
// en Phase 1 PoA (Aura block author NO surfaced canonical via Authorship trait).
// Gas rebates al block author NO operativos en Slice 3.1 — acceptable en
// dev/testnet. Phase 4 testnet decide canonical: add pallet_authorship OR
// custom FindAuthor extracting de Aura digests pre-header inspection.
// - `AddressMapper = pallet_revive::AccountId32Mapper<Self>`: canonical para
// solochain — mapea AccountId32 ↔ H160 EVM addresses via BLAKE2b derivation.
//
// **OriginChainId 9_120_005**: EIP-155 unique canonical para Origin Metaverse.
// Pattern fecha-encoded (9=Sept simbólico inicio Genesis 2026, 12=Dec roadmap,
// 05=número simbólico David Herran founder). Previene replay attacks cross-chain.
parameter_types! {
/// Storage deposit canonical per byte de contract data stored.
/// Pattern Asset Hub canonical: 1 MILLI_OGC per byte = 10^15 base units.
/// Phase 3.x maduración refinement con Mathi OitFeeSchedule canonical.
/// Slice 3.1 SCAFFOLD initial estimate empirical-validated por
/// `__construct_runtime_integrity_test` pallet-revive 0.10.1 storage
/// size limit (formula derives max storage from DepositPerByte rate).
pub const ReviveDepositPerByte: Balance = MILLI_OGC;
/// Storage deposit canonical per storage item (key-value entry).
/// Pattern Asset Hub canonical: 1 OGC per item = 10^18 base units
/// (significantly higher than per-byte to economically gate canonical
/// storage item proliferation). Refunds canonical pro-rata via
/// `pallet-revive` design (refund-on-terminate canonical).
pub const ReviveDepositPerItem: Balance = OGC;
/// Code hash lockup deposit percentage canonical.
/// 30% canonical Asset Hub reference — locks 30% del storage deposit cuando
/// se instantiate desde un code hash, para protect code de unlikely deletion
/// mientras existen contract instances usándolo. Refunded canonical cuando
/// el último contract usando ese code es terminated.
pub ReviveCodeHashLockupDepositPercent: Perbill = Perbill::from_percent(30);
}
impl pallet_revive::Config for Runtime {
// ── Runtime types (stable2509-3 pallet-revive 0.10.1 surface, 22 required types) ──
type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall;
type RuntimeHoldReason = RuntimeHoldReason;
// ── Currency & Balance ─────────────────────────────────────
type Currency = crate::Balances;
type Time = crate::Timestamp;
/// WeightPrice canonical: Convert<Weight, Balance> via TransactionPayment.
/// pallet_transaction_payment::Pallet implementa Convert<Weight, BalanceOf>
/// per Asset Hub canonical reference pattern.
type WeightPrice = pallet_transaction_payment::Pallet<Runtime>;
// ── Storage & Deposit ──────────────────────────────────────
type DepositPerByte = ReviveDepositPerByte;
type DepositPerItem = ReviveDepositPerItem;
type CodeHashLockupDepositPercent = ReviveCodeHashLockupDepositPercent;
// ── EVM & Address Mapping ──────────────────────────────────
type AddressMapper = pallet_revive::AccountId32Mapper<Self>;
type ChainId = ConstU64<9_120_005>; // Origin Metaverse EIP-155 unique
type NativeToEthRatio = ConstU32<1_000_000>; // OGC 12 decimals → ETH 18 decimals
type AllowEVMBytecode = ConstBool<true>; // Solidity contracts canonical
/// EthGasEncoder canonical: gas ↔ balance conversion para EVM-style
/// transactions. Empty tuple `()` usa default canonical pallet-revive
/// para Slice 3.1 SCAFFOLD (1:1 mapping). Phase 3.x maduración custom.
type EthGasEncoder = ();
// ── Precompiles ────────────────────────────────────────────
// Slice 3.1 SCAFFOLD interim: empty tuple placeholder. Phase 3.x maduración.
type Precompiles = ();
// ── Execution Limits & Memory ──────────────────────────────
// pallet-revive 0.10.1 stable2509-3 integrity test formula canonical:
// storage_limit = (PVFMemory - RuntimeMemory) / 2
// max_storage_size = computed ~650 MB from BlockWeights + SetStorage cost
// Need PVFMemory > RuntimeMemory + 1.3 GB para pass integrity_test canonical.
// Asset Hub pattern: 128 MB runtime + 512 MB PVF NO works en 0.10.1 (limit
// would be 192 MB but max_storage 650 MB). Slice 3.1 SCAFFOLD bumps PVFMemory
// a 2 GB para satisfy integrity check (PVFMemory MEMORY-ONLY limit, no actual
// RAM allocation pre-validator load — Pi 5 8 GB RAM tier safe). Phase 3.x
// refinement post-real benchmarks.
type WeightInfo = pallet_revive::weights::SubstrateWeight<Self>;
type RuntimeMemory = ConstU32<{ 128 * 1024 * 1024 }>; // 128 MB runtime allocation
type PVFMemory = ConstU32<{ 2 * 1024 * 1024 * 1024 }>; // 2 GB validator PVF memory limit
// ── Access Control ─────────────────────────────────────────
type UploadOrigin = EnsureSigned<ChainAccountId>;
type InstantiateOrigin = EnsureSigned<ChainAccountId>;
// ── Authorship + Safety toggles ────────────────────────────
// pallet-revive 0.10.1 stable2509-3 NO expone DebugEnabled (added 0.12+).
// RuntimeOrigin NO expone direct (consumed transitively via RuntimeCall).
// FeeInfo NO expone (added 0.12+). MaxEthExtrinsicWeight NO expone (added 0.12+).
// GasScale NO expone (added 0.12+). DepositPerChildTrieItem NO expone (added 0.12+).
type FindAuthor = (); // returns None Slice 3.1 (sin pallet_authorship)
type UnsafeUnstableInterface = ConstBool<false>; // testnet-only feature gate
}
// ============================================================
// pallet_sudo::Config — FIX-5 governability (Root origin, audit V2-CA1)
// ============================================================
//
// La cadena no se gobernaba: las dispatchables admin de Governance (add/remove
// council, mark/unmark advisor, treasury_disbursement — todas `ensure_root`)
// eran no-invocables sin un Root origin, y la tesorería 250M quedaba congelada.
// pallet-sudo provee Root origin canonical vía una sudo key única.
//
// SUNSET canonical: la sudo key es interim (Foundation multisig humano, seteada
// en genesis). ANTES de mainnet se migra a governance real (pallet-collective +
// pallet-referenda) y se remueve sudo — la cadena se auto-gobierna sin Root.
impl pallet_sudo::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall;
type WeightInfo = pallet_sudo::weights::SubstrateWeight<Runtime>;
}