FerroCore Technicals
AIFerroCore architecture followed by a code-level record of the first execution-replay slice.
Definition
Mission: Build an inspectable path from a coherently converted indicator suite to account-sized crypto portfolio decisions through a dynamic, multi-timeframe, crypto-native rebalancer that treats execution and risk as part of the result.
Vision
Market observation, indicator logic, sector classification, portfolio policy, execution replay, accounting, runtime authority, and presentation should be independently testable and replaceable. The interface should follow verified models and records instead of defining them.
First real minimum viable product
The first real MVP is a dynamic multi-timeframe crypto-native rebalancer, done right.
- Minimum universe
- BTC and ETH.
- Equivalence
- Include ETH-equivalent assets while preserving their individual identity and added risk.
- Yield
- Account for the trade-off between additional yield and the additional risk required to obtain it.
- Exposure boundary
- Avoid unreasonable exposure such as leverage.
- Time structure
- Use multiple timeframes dynamically; the timeframe set, interaction rules, and rebalance triggers remain to be specified.
- Portfolio posture
- Zero direct stablecoin exposure is being taken seriously; the exact accounting and execution consequences remain to be specified.
ETH equivalence describes a portfolio role, not equality of risk. “Crypto-native” establishes the intended asset posture here; it does not yet select a chain, venue, custody model, wrapper, or accounting reference. The broader mostly Etherian sector/TAM model may extend the MVP; the exact initial universe beyond the BTC/ETH floor remains open.
Goals and sequence
- Now
- Define the architecture and its contracts; continue converting the indicator suite coherently; specify the multi-timeframe rebalancer, BTC/ETH floor, ETH-equivalence model, yield/risk treatment, and exposure limits without reviving the SynthCore frontend.
- Research path
- Publish the original Pine indicators over the next season while working toward parity or better with relevant open-source indicators.
- System path
- Separate observed markets from account-sized executable claims; add explicit intent, submission-policy, ledger, and reconciliation boundaries above the current block-pinned foundation.
- Later
- Extend into the broader sector/TAM model and harden strategies only after their inputs, portfolio decisions, execution assumptions, and accounting can be inspected independently. Signing remains beyond replay, forward shadow execution, and bounded-canary reconciliation.
This sequence does not establish a release date, approved strategy, or live-trading commitment.
MVP decision ledger
This separates the product definition already stated from decisions that still require human authorship.
| area | established direction | open decisions |
|---|---|---|
| Product | Dynamic multi-timeframe crypto-native rebalancer. | The exact objective function and acceptance criteria for “done right.” |
| Minimum universe | BTC and ETH. | Any additional MVP assets and their eligibility process. |
| ETH equivalence | ETH-equivalent assets belong in scope without erasing their added risk. | Exact membership, equivalence tests, and whether each asset receives a separate risk budget. |
| Yield | Additional yield must be evaluated with the additional risk required to obtain it. | Yield source, observation window, net-yield calculation, risk measures, and comparison rule. |
| Exposure | Unreasonable exposure such as leverage is outside the MVP. | Concentration limits, minimum/maximum weights, turnover limits, and other portfolio bounds. |
| Stablecoins | Zero direct stablecoin exposure is an active design constraint. | The analytical accounting reference; measurement denomination is distinct from holding an asset. |
| Timeframes | More than one timeframe must affect the system dynamically. | The timeframe set, synchronization rule, and whether timeframes form a hierarchy, a combined decision, or independent sleeves. |
| Rebalance | The system changes portfolio targets rather than only emitting an isolated trade signal. | Triggers, cadence, hysteresis, decision persistence, and handling of conflicting timeframe states. |
| Execution | Claims should be account-sized and bound to declared chain state and assumptions. | Chains, venues, routes, cost model, submission policy, and allowable execution latency. |
| Evaluation | Observed prices and candle closes are not automatically executable results. | Benchmarks, relative performance references, risk reporting, and promotion gates between replay, shadow, and canary modes. |
Compartmental architecture
The table below separates system responsibilities. Names describe zones, not implemented Rust types.
market observation ──▶ multi-timeframe research ──┐
asset / equivalence / yield model ────────────────┼─▶ portfolio policy ─▶ targets
sector / universe model (extension) ──────────────┘
targets ─▶ intent + submission policy ─▶ replay / shadow / bounded canary
chain archive + pinned state ─────────────────────▲ │
▼
ledger ─▶ views
signing / broadcasting: absent; later isolated behind runtime authority
| zone | owns | required handoff | current state |
|---|---|---|---|
| Market observation | Raw trades, quotes, swaps, normalized events, and candles. | Versioned observations with source, instrument, time, and quality identity. | SynthCandles exists separately; not FerroCore 0.1.0. |
| Multi-timeframe research | Indicator definitions, parameters, timeframe-specific state, and the declared rules for combining or separating timeframes. | A versioned indicator-state record with instrument, timeframe, observation time, and no wallet, router, or presentation dependency. | Indicator conversion is ongoing; final handoff and timeframe interaction are undefined. |
| Asset, equivalence, and yield model | BTC/ETH identity, ETH-equivalent membership, the source of additional yield, and the added risk attached to each asset. | A dated asset record that preserves identity while declaring portfolio role, yield, and assessed risk. | Minimum concepts are stated; measurement and eligibility rules are not implemented. |
| Sector and universe model | Broader taxonomy, universe membership, exclusions, class relationships, and Etherian-focused TAM definitions. | A dated, versioned universe snapshot consumed by portfolio policy. | Expansion design; classifications remain open. |
| Portfolio policy | Dynamic multi-timeframe weighting, risk/yield trade-offs, exposure bounds, rebalance triggers, cadence, and turnover constraints. | Target allocations plus reasons and the policy version that produced them. | Not implemented. BTC/ETH is the minimum scope; leverage is outside the MVP. |
| Intent and submission policy | Translate target deltas into account-sized actions; accept or reject them under declared timing, route, cost, and state assumptions. | An immutable intent and an explicit decision record. | Declared architectural responsibility; not implemented. |
| Execution state and replay | Pinned chain state, archived events, historical quote inputs, quote results, and later cost modeling. | A reproducible execution result bound to its assumptions and state. | Partially implemented by ferro-backfill and ferro-quote. |
| Ledger and reconciliation | Asset-unit balances, portfolio state transitions, costs, and differences between expected and observed results. | An append-only accounting record and reconciled state. | Declared architectural responsibility; not implemented. |
| Runtime authority | Replay, forward shadow, bounded canary, and any later signing or broadcasting permissions. | An explicit mode and approval boundary; no implicit escalation of authority. | Replay foundations only. No keys, signer, or broadcaster. |
| Views and documentation | Human-readable explanations, diagnostics, status, and later interaction surfaces. | Read models derived from system records. | SynthCore frontend is retired; stronger replacement deferred. |
Independence rules
- Observation records do not contain strategy or portfolio decisions.
- Indicator logic does not own the asset universe, wallet state, execution route, or interface.
- Timeframe identity remains explicit; combining timeframes is a portfolio-policy decision rather than an ingestion side effect.
- ETH and ETH-equivalent assets retain separate identities. Portfolio equivalence cannot silently erase different yield sources or risks.
- The asset/universe models and portfolio policy are versioned separately so an eligibility change is not silently a strategy change.
- Portfolio policy emits targets; it does not invent fills, apply leverage, or mutate balances.
- Execution evaluates declared intents; it does not decide which assets deserve capital.
- The ledger consumes explicit results and remains independent from candle construction and display formatting.
- Signing and custody remain isolated behind a later authority boundary rather than becoming ambient library capability.
- The frontend reads system state; it is not the canonical store for research, policy, execution, or accounting.
Current code boundary
The question declared by the project is narrower than a candle backtest: what would an account-sized transaction have done under a declared submission policy at a specific Ethereum state?
The repository assigns broad market collection and candle construction to SynthCandles. It assigns block-pinned execution state, intent acceptance, and a reproducible cash ledger to FerroCore. That second statement is architectural direction, not the present implementation: version 0.1.0 contains archive and quote foundations but no general submission-policy type, portfolio ledger, or transaction executor.
The current crate is not the MVP rebalancer. It does not combine timeframes, define BTC/ETH weights, classify ETH equivalents, measure risk-adjusted yield, or emit rebalance decisions.
- crate
- ferrocore 0.1.0 · Rust 2021
- archive schema
- 1
- programs
- ferro-backfill · ferro-quote
- implemented scope
- one-pool V3 archive · one-hop V3 quote · pure stable assessment
- local verification
- 11 unit tests passed · 2026-07-17
- external verification
- none established by the available source record
Command-line interface
ferro-backfill <pool> <from-block> <to-block> <output.jsonl>
[--rpc URL] [--chunk BLOCKS]
ferro-quote <block> <token-in> <token-out> <fee> <amount-in-raw>
[--rpc URL] [--quoter ADDRESS]
Both commands accept the endpoint through ETH_RPC_URL or --rpc. The backfill chunk defaults to 2,000 blocks. The quote amount is an unsigned base-10 integer in the token's smallest units. ferro-quote prints one JSON result; ferro-backfill writes JSONL plus a manifest and prints a completion summary to standard error.
Historical swap archive
ferro-backfill requests logs matching the Uniswap V3 Swap signature for one declared pool and inclusive block range.
Write path
- Canonicalize the pool address; reject a reversed range or zero block chunk.
- Read the chain ID and complete starting and ending block references.
- Request logs in ascending block chunks, then sort each response by block number, transaction index, and log index.
- Fetch only the headers referenced by returned logs, in JSON-RPC batches of at most 100.
- Decode and validate each event, reject duplicate event identities, and append exact serialized bytes to a process-specific temporary JSONL file while computing SHA-256.
- Flush and sync the temporary file. Fetch the ending block again and reject the run if its hash changed.
- Rename the JSONL into place, then write and rename a separate manifest file.
Schema-v1 event
Each event records schema version, chain ID, canonical log address, complete block reference, transaction hash and index, log index, sender, recipient, signed raw amount0 and amount1, sqrtPriceX96, active liquidity, tick, and the original five-word ABI data field. Amount and price-state values are serialized as decimal strings rather than floating-point numbers.
The event identity is block hash : transaction hash : log index. The record does not contain token addresses, token decimals, pool fee tier, human display amounts, or a derived execution price.
Manifest
The manifest records schema version, product name, chain ID, declared pool, starting and ending block references, event count, SHA-256 of the exact JSONL byte stream, and generation time. The digest detects a changed byte stream after generation. It does not authenticate the RPC provider or prove that the returned logs were complete.
What the code enforces
- Explicit pool syntax and inclusive block range.
- Swap topic signature and at least the expected indexed topics.
- Exactly five 32-byte data words.
- Log block number and hash matching the fetched header.
- Canonical address/hash shapes and zero-padded topic addresses.
- Signed amount decoding and an
int24-sized tick. - No removed logs or duplicate event identities.
- An unchanged ending block hash during the run.
Current trust and validation gaps
- The RPC provider remains a trusted data source; no second provider or independent chain proof is consulted.
- The manifest does not record crate version, RPC-provider identity, or the selected request chunk.
- The returned log address is recorded but is not explicitly compared with the configured pool before output.
sqrtPriceX96and liquidity are decoded as full 256-bit unsigned words; their declareduint160anduint128widths are not enforced.- Tick validation enforces the ABI
int24range, not Uniswap V3's narrower protocol tick range. - The JSONL is renamed before the manifest is written, so the two files are not committed as one atomic pair.
- The files are synced, but the containing directory is not explicitly synced after rename.
- The operator chooses a finalized range; the code does not calculate or enforce finality depth.
Block-pinned quote
ferro-quote fetches a block reference by number, constructs calldata for quoteExactInputSingle((address,address,uint256,uint24,uint160)), and calls the configured QuoterV2 address using that block hash with requireCanonical: true. The CLI defaults to the mainnet QuoterV2 address defined by the crate and sets sqrtPriceLimitX96 to zero.
The intent records chain ID, complete block reference, quoter, token addresses, fee, raw input amount, and price limit. Validation canonicalizes addresses; rejects identical tokens, zero input, an input wider than uint256, a fee wider than uint24, and a price limit wider than uint160; and never converts through floating point.
The decoder requires exactly four ABI words and returns raw amount out, post-swap sqrtPriceX96, initialized ticks crossed, and QuoterV2's pool-swap gas estimate.
Interpretation boundary
- This is a one-hop, exact-input-single quote for one fee tier—not route discovery or order splitting.
- The result is an
eth_callagainst QuoterV2, not a router transaction, submitted order, or observed fill. - Router overhead, calldata gas, priority fee, base-fee payment, inclusion delay, MEV, and submission policy are absent.
- The code does not verify token bytecode, pool existence, enabled fee tiers, quoter bytecode, or liquidity before the call.
- The default quoter constant is mainnet-specific; selecting another chain requires the operator to supply the correct address.
- The CLI obtains chain ID and block reference from its RPC client, but the reusable intent type does not itself prove that its chain ID, block fields, and provider all agree.
requireCanonicalasks the provider to reject a noncanonical hash; it does not remove provider trust.
RPC transport and failure behavior
- transport
- HTTP or HTTPS · rustls for TLS
- request IDs
- monotonic process-local integers
- header batches
- maximum 100 requests
- HTTP retries
- 429 and 5xx · up to 8 retries after the first attempt
- retry delay
- integer Retry-After seconds, or 250 ms exponential backoff · clamped to 15 s
- not retried
- transport failures, JSON-RPC errors in HTTP 200 responses, decode failures
The client has no explicit request timeout. Transport errors are reduced to method plus a general failure class so the endpoint URL is not echoed. Non-success HTTP bodies are whitespace-compacted and capped at 500 characters. JSON-RPC error messages returned inside a successful HTTP response are preserved as supplied by the provider.
Failures remain typed: invalid arguments or hex, invalid swap data, transport/HTTP/JSON-RPC failures, missing results, reorganization, duplicates, removed logs, filesystem errors, and JSON errors stop the operation rather than being converted into a plausible quote or partial success.
StableGuard module
StableGuard is a pure assessment function from an earlier stable-asset accounting design. It does not fetch oracle, Curve, depth, or token data. A caller supplies token identity, direct and optional Curve-derived prices, optional Curve imbalance, executable depth, and oracle age.
Prices use integer parts per million, where 1,000,000 equals one dollar. Valuation takes the lowest supplied observation and caps it at one dollar. Default thresholds are a 50-basis-point soft deviation, 200-basis-point hard deviation, 2,500-basis-point maximum Curve imbalance, $100,000 minimum caller-reported executable depth, and 300-second maximum oracle age. Price deviation is absolute, so a sufficiently large over-peg observation can also halt eligibility even though valuation never exceeds one dollar.
A soft deviation returns Haircut while leaving the asset eligible as a quote. A hard deviation, stale oracle, insufficient depth, or excessive supplied imbalance returns Halted. Curve data is optional; its absence does not itself halt an assessment.
This module is implemented but is not wired to either CLI. Its presence does not establish portfolio exposure or override the current design direction taking zero direct stablecoin exposure seriously.
Verification record
cargo test --offline passed locally on 2026-07-17: 11 passed, 0 failed, 0 ignored.
| module | tests | covered |
|---|---|---|
| archive | 2 | pool canonicalization, valid range, reversed-range rejection |
| quote | 3 | calldata word placement, four-word decoding, zero amount and identical-token rejection |
| risk | 3 | healthy valuation, hard depeg, stale-or-imbalanced halt |
| Uniswap decoder | 3 | lossless identity/state fields, mismatched block hash, removed log |
Not established by those tests
- No archive filesystem, digest, manifest, reorganization, or atomic-replacement integration test.
- No RPC batch, retry, timeout, provider-divergence, or error-sanitization test.
- No live or recorded mainnet quote fixture and no comparison with an executed router transaction.
- No CLI tests, fuzz tests, property tests, or external audit.
- No evidence yet for a submission policy, cash ledger, forward shadow executor, bounded canary, or live reconciliation.
Open engineering review targets
- Decide and test the exact archive commit protocol, including JSONL/manifest pairing and crash recovery.
- Decide whether pool-address equality, ABI integer widths, protocol tick limits, token metadata, and fee tier belong in schema 1 or a later schema.
- Define provider provenance and the level of independent verification required before an archive is accepted.
- Define a quote record that binds network, provider state, quoter identity, assumptions, and any later cost model.
- Specify intent acceptance, submission policy, ledger transitions, and reconciliation before describing FerroCore as an execution engine rather than an execution-replay foundation.
No keys, signing, broadcasting, custody, order placement, treasury integration, Tri-Pass integration, approved asset universe, approved sector taxonomy, weighting system, rebalance policy, or hardened strategy exists in this code slice.