Quantillon Protocol Architecture
Overview
The Quantillon Protocol is a sophisticated DeFi ecosystem built around a euro-pegged stablecoin (QEURO) with advanced yield management and risk mitigation systems. The architecture is designed for scalability, security, and efficient capital utilization.
The staking layer now supports a multi-vault model through stQEUROFactory: each staking vault has its own non-fungible staking token instance (stQEURO{vaultName}).
Versioning. Every core contract implements IVersioned.version() (a pure semver getter reflecting the deployed implementation); linked libraries expose version() and inlined libraries carry a VERSION constant. Any change to a deployed contract/library must be traced through a semver bump (enforced by make check-version-bump); deployments/{chainId}/versions.json records the live version + commit per contract. See Deployment.md → "Versioning & Provenance".
System Architecture
High-Level Architecture
┌─────────────────────────────────────────────────────────────────┐
│ SYSTEM ARCHITECTURE │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ User Layer │ │ Protocol Layer │ │ Yield Layer │
├─────────────────┤ ├─────────────────┤ ├─────────────────┤
│ • Retail Users │───▶│ • QuantillonVault│ │ • Ext. Vaults │
│ • Institutional │ │ • QEUROToken │ │ • YieldShift │
│ • Liquidity │ │ • QTIToken │ └─────────────────┘
│ Providers │ │ • FeeCollector │ │
└─────────────────┘ │ • UserPool │ │
│ • HedgerPool │ │
│ • stQEUROToken │ │
└─────────────────┘ │
│ │
┌─────────────────┐ │
│Infrastructure │ │
│Layer │ │
├─────────────────┤ │
│ • OracleRouter │ │
│ • TimeProvider │ │
│ • Security Libs │ │
└─────────────────┘ │
│ │
┌─────────────────┐ │
│External Systems │ │
├─────────────────┤ │
│ • Morpho │◀────────────┘
│ (MetaMorpho) │
│ • Hyperliquid │
│ • Chainlink │
│ • Base Network │
└─────────────────┘
Core Components
1. QuantillonVault
Purpose: Central vault managing QEURO minting and redemption against USDC collateral.
Key Responsibilities:
- Overcollateralized QEURO minting
- USDC collateral management
- Oracle price validation
- Liquidation-mode redemption when protocol CR is at or below the critical ratio (101%)
- Fee collection and distribution
Architecture Patterns:
- Proxy Pattern: Upgradeable implementation
- Access Control: Role-based permissions
- Reentrancy Protection: Secure external calls
- Circuit Breaker: Emergency pause mechanisms
2. QEUROToken
Purpose: Euro-pegged stablecoin with compliance and governance features.
Key Features:
- ERC-20 compliant with extensions
- Mint/burn controls via vault
- Compliance features (whitelist/blacklist)
- Rate limiting mechanisms
- Supply cap management
Architecture Patterns:
- Factory Pattern: Controlled token creation
- Observer Pattern: Event-driven compliance
- State Machine: Pause/unpause states
3. QTIToken
Purpose: Governance token with vote-escrow mechanics for protocol governance.
Status: dormant. No mint path is wired in the deployed contract, so total supply is 0 and lock/vote/propose are inactive until a future activation upgrade mints the cap. The features below describe the intended design.
Key Features:
- Vote-escrow token mechanics
- Time-weighted voting power
- Governance proposal system
- Delegation capabilities
- Lock period management
Architecture Patterns:
- Escrow Pattern: Time-locked voting power; topping up an existing lock recomputes voting power over the full merged position (not just the added amount)
- Voting System: On-chain self-execution — the token holds
GOVERNANCE_ROLE, so a passed proposal executes its own role-gated calldata after a mandatory post-vote timelock (PROPOSAL_EXECUTION_DELAY, 2 days). Activation requires the Safe to grantGOVERNANCE_ROLEto the QTI proxy. - Decay Function: Linear voting power decay
4. UserPool
Purpose: Optional batch front-end for deposits (USDC → QEURO through the vault) and QEURO staking with an unstaking cooldown.
Key Features:
- Batched USDC deposit / QEURO withdrawal routed through
QuantillonVault - QEURO staking with
requestUnstake→ 7-day cooldown →unstake - Pending-withdrawal escrow when a USDC transfer to the user fails
- User position tracking (
getUserInfo) - No reward claim: user yield accrues through stQEURO (ERC-4626 share price)
Architecture Patterns:
- Pool Pattern: Centralized escrow of staked QEURO
- Cooldown Gate: Time-locked unstaking
- State Tracking: User position management
5. HedgerPool
Purpose: Manages leveraged hedging positions for risk management.
Key Features:
- EUR/USD hedging positions
- Margin management system
- Liquidation mechanisms
- Position tracking and PnL calculation
- Risk parameter management
Architecture Patterns:
- Position Management: Individual position tracking
- Margin System: Collateral and leverage management
- Liquidation Engine: Automated risk management
- Oracle Integration: Price feed validation
6. stQEUROToken
Purpose: Yield-bearing wrapper for QEURO with automatic yield accrual.
Key Features:
- Automatic yield distribution via exchange rate
- Exchange rate =
totalAssets() / totalSupply()(standard ERC-4626 share price; it rises whenQuantillonVault.creditVaultYieldmints QEURO into the token without minting shares) - No lock-up period — unstake at any time
- Virtual protection against donation attacks
Architecture Patterns:
- Wrapper Pattern: Enhanced token functionality
- Yield Distribution: Exchange rate increases as yield accrues
- Virtual Protection: Attack prevention mechanisms
6b. stQEUROFactory (Multi-Vault Extension)
Purpose: Factory/orchestrator that deploys one stQEUROToken proxy per staking vault.
Key Features:
- Per-vault token deployment using
ERC1967Proxyand sharedstQEUROTokenimplementation - Deterministic registry and lookup mappings:
vaultId -> stQEURO tokenvault -> stQEURO tokenstQEURO token -> vaultId
- Strict vault self-registration model (
msg.senderis the registered vault) - Validation and uniqueness guarantees for
vaultIdandvaultName(uppercase alphanumeric) - Governance-controlled factory config (implementation/yieldShift/treasury/token admin)
Architecture Patterns:
- Factory Pattern: Dynamic deployment of homogeneous staking-token proxies
- Registry Pattern: Bi-directional mapping between vaults and staking tokens
- Role-Gated Self-Registration: Vault onboarding constrained by governance-granted role + on-chain self-call
7. FeeCollector
Purpose: Centralized fee collection and distribution across the protocol.
Key Features:
- Collects fees from QuantillonVault (mint/redeem fees)
- Distributes to three beneficiaries: treasury (60%), dev fund (25%), community (15%)
- Governance-controlled ratio updates
- Per-token fee accounting
Architecture Patterns:
- Pull Pattern: Beneficiaries withdraw collected fees
- Split Pattern: Configurable fee ratio distribution
8. OracleRouter
Purpose: Oracle-agnostic price routing — all protocol contracts interact with OracleRouter via IOracle.
Key Features:
- Holds two EUR/USD oracle slots and routes all
IOraclereads to the active one - Slot 0 =
ChainlinkOracle(fallback); slot 1 =HyperliquidEurUsdOracle(active since the governance switch of 2026-06-25) - Governance switches sources at runtime via
switchOracle— no protocol-contract changes updateOracleAddressesrepoints a slot;OracleSwitchedevent on switch
9. EUR/USD Oracles (HyperliquidEurUsdOracle · ChainlinkOracle · StorkOracle)
Purpose: EUR/USD pricing with freshness checks, price bounds, and deviation circuit breakers. All implement IOracle, so the router (and thus the protocol) is source-agnostic.
Key Features:
- HyperliquidEurUsdOracle (active): mirrors the Hyperliquid
xyz:EURperpetual mid — the venue where the protocol's EUR/USD hedge executes — so QEURO mint/redeem aligns with the hedge. Reads the mid fromSlippageStorage(published on-chain by the off-chain Slippage Monitor) and delegates USDC/USD to theChainlinkOracle. Configurable staleness (default 900s), bounds (0.80–1.40e18), 5% deviation circuit breaker, last-valid fallback. - ChainlinkOracle (fallback): Chainlink AggregatorV3 EUR/USD + USDC/USD; 2-hour EUR/USD staleness (25h for USDC/USD, matching its daily heartbeat), 5% deviation circuit breaker. Also the protocol's USDC/USD validation source.
- StorkOracle: Stork Network
TemporalNumericValuefeeds (legacy/parked; the slot-1 position is now occupied byHyperliquidEurUsdOracle). - Mock versions available (
MockChainlinkOracle,MockStorkOracle) for local/testnet. - Full design: Oracle Architecture.
9b. SlippageStorage
Purpose: On-chain store written by the off-chain Slippage Monitor; holds the published Hyperliquid xyz:EUR mid per source, which HyperliquidEurUsdOracle reads. WRITER_ROLE-gated writes with an on-chain minimum-interval rate limit.
10. TimeProvider
Purpose: Centralized block.timestamp wrapper for consistent time management across all contracts.
Yield Management Architecture
YieldShift System
Purpose: Intelligent yield distribution between user and hedger pools.
Components:
- Yield Sources: external staking vaults (MetaMorpho live via
MetaMorphoStakingVaultAdapter; Morpho/Aave adapters for localhost), protocol fees, interest differentials - Distribution Engine: Dynamic allocation between pools
- Performance Metrics: Yield tracking and optimization
- Rebalancing Logic: Automatic pool rebalancing
Architecture Patterns:
- Strategy Pattern: Multiple yield source strategies
- Observer Pattern: Performance monitoring
- Factory-Routed Distribution: Yield routed by
vaultIdthroughstQEUROFactoryto the correct staking token
External Staking Vault Integration
Purpose: Yield generation by deploying protocol USDC into external yield vaults (MetaMorpho live in production; Morpho/Aave adapters available).
Features:
- USDC deployment per
vaultIdviaQuantillonVault.deployUsdcToVault - Yield harvesting and distribution via
harvestAndDistributeVaultYield - One stQEURO series per vault (isolated yield accounting)
- Governance-gated exposure decisions per vault
Architecture Patterns:
- Adapter Pattern: thin
IExternalStakingVaultadapters wrap each external vault - Factory Registry:
stQEUROFactorymapsvaultIdto adapter + stQEURO series - Yield Optimization: Dynamic allocation strategies
- Vault-Aware Routing: harvested external-vault yield is split by
QuantillonVault.harvestAndDistributeVaultYield(hedger funding / stQEURO stakers / treasury);YieldShift.addYield(vaultId, ...)stays available for other authorized sources
Security Architecture
Access Control System
Role-Based Access Control (RBAC):
MINTER_ROLE/BURNER_ROLE: QEUROToken — vault-only mint/burnPAUSER_ROLE: QEUROToken emergency pause and minting killswitchCOMPLIANCE_ROLE: QEUROToken blacklist/whitelist managementGOVERNANCE_ROLE: Parameter updates and contract wiring across all core contracts (on FeeCollector it also gates upgrades)EMERGENCY_ROLE: Emergency pause and withdrawal across all core contracts; oracle circuit breakersVAULT_OPERATOR_ROLE: QuantillonVault —deployUsdcToVault(USDC deployment into any registered external vault adapter)YIELD_DISTRIBUTOR_ROLE: QuantillonVault —harvestAndDistributeVaultYield/creditVaultYield- Hedging: no dedicated role — HedgerPool uses a single-hedger allowlist (
setSingleHedger) VAULT_FACTORY_ROLE: stQEUROFactory — vault self-registrationTREASURY_ROLE/FEE_SOURCE_ROLE: FeeCollector — fee distribution / authorized fee sourcesORACLE_MANAGER_ROLE: OracleRouter / ChainlinkOracle / HyperliquidEurUsdOracle / StorkOracle / LighterEurUsdOracle (inert) — feed updates, oracle switchingMANAGER_ROLE/WRITER_ROLE: SlippageStorage — store configuration / on-chain mid publishingUPGRADER_ROLE: the plain-UUPS proxies (oracles, SlippageStorage) — direct Safe upgrades; theSecureUpgradeablecore proxies are gated by the 12 h TimelockController instead
Security Patterns
Reentrancy Protection:
nonReentrantmodifier on all state-changing functions- Checks-effects-interactions pattern
- External call isolation
Oracle Security:
- Multiple price feed validation
- Staleness checks
- Circuit breaker mechanisms
- Price bound validation
Emergency Systems:
- Pause/unpause mechanisms
- Emergency withdrawal functions
- Circuit breaker activation
- Recovery procedures
Data Flow Architecture
QEURO Minting Flow
QEURO Minting Flow:
┌─────────┐ ┌──────────────┐ ┌─────────────────┐ ┌─────────────┐
│ User │ │QuantillonVault│ │ OracleRouter │ │QEUROToken │
└────┬────┘ └──────┬───────┘ └────────┬────────┘ └──────┬──────┘
│ │ │ │
│ approve() │ │ │
├───────────────▶│ │ │
│ mintQEURO() │ │ │
├───────────────▶│ │ │
│ │ getEurUsdPrice() │ │
│ ├─────────────────────▶│ → active slot │
│ │ price, isValid │ (HyperliquidEurUsdOracle)
│ │◀─────────────────────┤ │
│ │ validatePrice() │ │
│ │ calculateMintAmount()│ │
│ │ transferFrom() │ │
│ │ mint() │ │
│ ├─────────────────────────────────────────▶│
│ │ emit QEUROminted() │ │
│ success │ │ │
│◀───────────────┤ │ │
OracleRouter forwards getEurUsdPrice() to its active slot (HyperliquidEurUsdOracle since 2026-06-25; ChainlinkOracle as fallback). The read is non-view — a fresh valid price refreshes the deviation baseline — and isValid = false reverts the mint with InvalidOraclePrice.
Yield Distribution Flow
Yield Distribution Flow (QuantillonVault.harvestAndDistributeVaultYield):
┌──────────┐ ┌───────────────┐ ┌──────────────┐ ┌───────────┐ ┌───────────────┐
│ Keeper │ │QuantillonVault│ │ Ext. adapter │ │ stQEURO │ │ hedger recip. │
│ (YIELD_ │ │ │ │ (MetaMorpho) │ │(per vault)│ │ / treasury │
│DISTRIB.) │ │ │ │ │ │ │ │ │
└────┬─────┘ └───────┬───────┘ └──────┬───────┘ └─────┬─────┘ └───────┬───────┘
│ harvestAndDistributeVaultYield(vaultId) │ │
├─────────────▶│ │ │ │
│ │ harvestYieldToVault() │ │
│ ├─────────────────▶│ │ │
│ │ realizedYield (USDC above tracked principal) │
│ │◀─────────────────┤ │ │
│ │ hedgerShare = fundingRateAnnualBps × principal × Δt (paid first)
│ ├──────────────────────────────────────────────▶│
│ │ userShare → _creditVaultYield(): mint QEURO into stQEURO (share price ↑)
│ ├───────────────────────────────▶│ │
│ │ treasuryShare (USDC remainder) │ │
│ ├──────────────────────────────────────────────▶│
│ │ emit VaultYieldDistributed(vaultId, realizedYield, hedgerShare, userShare, treasuryShare)
See the Staking Yield Distribution guide for the split formula and parameters. YieldShift.addYield(vaultId, ...) remains the entrypoint for other authorized yield sources; external-vault yield no longer routes through it.
Governance Flow
Live governance on Base mainnet is the 2-of-3 Safe plus an OpenZeppelin TimelockController (12 h minDelay, Safe = sole proposer/executor). The QTI on-chain governance path (lock → createProposal → vote → self-execution after PROPOSAL_EXECUTION_DELAY) is coded but dormant: QTI supply is 0 and the token holds no GOVERNANCE_ROLE.
Governance Flow (live):
┌────────────┐ ┌───────────────────┐ ┌───────────────────────────┐
│ Safe (2/3) │ │ TimelockController│ │ SecureUpgradeable proxy │
└─────┬──────┘ └─────────┬─────────┘ └─────────────┬─────────────┘
│ schedule(upgradeToAndCall) │
├────────────────────▶│ │
│ ... 12 h minDelay ... │
│ execute() │ │
├────────────────────▶│ upgradeToAndCall(newImpl)
│ ├───────────────▶│ _authorizeUpgrade: msg.sender == timelock
│
│ Parameter changes on every contract, and upgrades of the plain-UUPS proxies
│ (FeeCollector, oracles, SlippageStorage): one direct Safe transaction on the
│ target (GOVERNANCE_ROLE / ORACLE_MANAGER_ROLE / UPGRADER_ROLE), no delay
├──────────────────────────────────────────────────▶ target contract
Scalability Architecture
Gas Optimization
Storage Optimization:
- Packed structs for efficient storage
- Batch operations for multiple updates
- Event-based logging instead of storage
- Minimal state variables
Computation Optimization:
- Cached values for repeated calculations
- Efficient algorithms for complex operations
- Minimal external calls
- Optimized loops and iterations
Upgradeability
Proxy Pattern Implementation:
- ERC1967 + UUPS proxies for every upgradeable contract (no transparent proxies)
- Core contracts inherit
SecureUpgradeable:_authorizeUpgraderequires the call to come from the configuredtimelock— on Base mainnet the 12 h OpenZeppelinTimelockController - Oracles, SlippageStorage and FeeCollector are plain UUPS proxies upgraded directly by the governance Safe (no timelock)
- Storage-layout compatibility and ABI additivity are enforced by
make check-upgrade-safety
Upgrade Process:
- Deploy and verify the new implementation (run
make check-verifiable-bytecode CONTRACT=<Name>first) - Validate compatibility (
make check-upgrade-safety: size, storage layout, ABI, version bump) SecureUpgradeableproxies: the Safe schedulesupgradeToAndCallon the TimelockController, waits 12 h, then executes; plain-UUPS proxies: the Safe callsupgradeToAndCalldirectly- Verify
version()on the proxy and record it indeployments/{chainId}/versions.json
Integration Architecture
External Integrations
Oracle System (OracleRouter + HyperliquidEurUsdOracle + ChainlinkOracle):
- OracleRouter implements
IOracle— all protocol contracts use this interface - Active oracle is switchable by governance (
switchOracle: Hyperliquid ↔ Chainlink) without contract changes; HyperliquidEurUsdOracle has been the active slot since 2026-06-25 - HyperliquidEurUsdOracle: Hyperliquid
xyz:EURperp mid read from SlippageStorage (published on-chain by the off-chain Slippage Monitor); 900 s staleness (1 h hard cap); 5% deviation circuit breaker; USDC/USD delegated to ChainlinkOracle - ChainlinkOracle: EUR/USD + USDC/USD via Chainlink AggregatorV3; 2 h EUR/USD staleness check (25 h USDC/USD); 5% deviation circuit breaker; Base L2 sequencer-uptime feed check
- StorkOracle: parked (former slot-1 oracle, still deployed). LighterEurUsdOracle: deployed 2026-07-17 and inert — the Lighter venue was not adopted (2026-09-01)
- MockChainlinkOracle + MockStorkOracle available for local/testnet development
External Yield Vaults (Morpho / Aave):
- USDC deployment through
IExternalStakingVaultadapters (MetaMorpho live, vaultId 2) - Yield harvesting and distribution via
QuantillonVault.harvestAndDistributeVaultYield - Governance-gated exposure per
vaultId - Emergency withdrawal mechanisms
ERC-20 Standards:
- Full ERC-20 compliance
- Extended functionality
- Metadata support
API Architecture
Contract Interfaces:
- Standardized function signatures
- Consistent error handling
- Event emission patterns
- Access control integration
Integration Patterns:
- Factory pattern for contract creation
- Registry pattern for contract discovery
- Proxy pattern for upgrades
- Adapter pattern for external integrations
Monitoring and Observability
Event Architecture
Core Events:
- Token transfers and approvals
- Vault operations (mint/redeem)
- Staking and unstaking
- Yield distribution
- Governance actions
Monitoring Events:
- System health indicators
- Performance metrics
- Error conditions
- Security events
Analytics Architecture
On-Chain Analytics:
- Transaction volume tracking
- Yield performance metrics
- User behavior analysis
- Risk metrics monitoring
Off-Chain Analytics:
- Protocol health dashboards
- Performance reporting
- Risk assessment
- Compliance monitoring
Architecture Principles
Design Principles
- Security First: All components designed with security as the primary concern
- Modularity: Clear separation of concerns and modular design
- Upgradeability: Future-proof design with upgrade capabilities
- Gas Efficiency: Optimized for cost-effective operations
- Transparency: Open and auditable code and processes
Development Principles
- Test-Driven Development: Comprehensive test coverage
- Documentation: Complete documentation for all components
- Code Review: Rigorous review process for all changes
- Continuous Integration: Automated testing and deployment
- Security Audits: Regular security assessments
This architecture document is maintained by Quantillon Labs and updated with each protocol version.